From 7d03118a9ebceb7882a83b0b0059bd0f6b8eacc2 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Thu, 9 Dec 2021 19:15:25 +0000 Subject: [PATCH 1/9] Add lexer parameter to Syntax --- rich/syntax.py | 11 +++++++++-- tests/test_syntax.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/rich/syntax.py b/rich/syntax.py index 05d41c993..4ef751e84 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -5,6 +5,7 @@ from abc import ABC, abstractmethod from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, Union +from pygments.lexer import Lexer from pygments.lexers import get_lexer_by_name, guess_lexer_for_filename from pygments.style import Style as PygmentsStyle from pygments.styles import get_style_by_name @@ -195,6 +196,7 @@ class Syntax(JupyterMixin): Args: code (str): Code to highlight. lexer_name (str): Lexer to use (see https://pygments.org/docs/lexers/) + lexer (Lexer): Lexer instance to use (see https://pygments.org/docs/lexers/) theme (str, optional): Color theme, aka Pygments style (see https://pygments.org/docs/styles/#getting-a-list-of-available-styles). Defaults to "monokai". dedent (bool, optional): Enable stripping of initial whitespace. Defaults to False. line_numbers (bool, optional): Enable rendering of line numbers. Defaults to False. @@ -226,8 +228,9 @@ def get_theme(cls, name: Union[str, SyntaxTheme]) -> SyntaxTheme: def __init__( self, code: str, - lexer_name: str, + lexer_name: Optional[str] = None, *, + lexer: Optional[Lexer] = None, theme: Union[str, SyntaxTheme] = DEFAULT_THEME, dedent: bool = False, line_numbers: bool = False, @@ -240,8 +243,12 @@ def __init__( background_color: Optional[str] = None, indent_guides: bool = False, ) -> None: + if all((lexer_name, lexer)): + raise ValueError("Cannot pass both lexer_name and lexer") + self.code = code self.lexer_name = lexer_name + self.lexer = lexer self.dedent = dedent self.line_numbers = line_numbers self.start_line = start_line @@ -374,7 +381,7 @@ def highlight( ) _get_theme_style = self._theme.get_style_for_token try: - lexer = get_lexer_by_name( + lexer = self.lexer or get_lexer_by_name( self.lexer_name, stripnl=False, ensurenl=True, diff --git a/tests/test_syntax.py b/tests/test_syntax.py index 090d08d25..3f8e5d3d4 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -10,6 +10,8 @@ from rich.style import Style from rich.syntax import Syntax, ANSISyntaxTheme, PygmentsSyntaxTheme, Color, Console +from pygments.lexers import PythonLexer + CODE = '''\ def loop_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]: @@ -27,6 +29,19 @@ def loop_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]: yield first, True, previous_value''' +def test_cannot_pass_both_lexer_name_and_lexer(): + code = "\n\nimport this\n\n" + with pytest.raises(ValueError, match="Cannot pass both lexer_name and lexer"): + Syntax( + code, + lexer_name="python", + lexer=PythonLexer, + theme="ascii_light", + code_width=30, + line_numbers=True, + ) + + def test_blank_lines(): code = "\n\nimport this\n\n" syntax = Syntax( @@ -74,6 +89,21 @@ def test_python_render_simple(): assert rendered_syntax == expected +def test_python_render_simple_passing_lexer_instance(): + syntax = Syntax( + CODE, + lexer=PythonLexer(), + line_numbers=False, + theme="foo", + code_width=60, + word_wrap=False, + ) + rendered_syntax = render(syntax) + print(repr(rendered_syntax)) + expected = '\x1b[1;38;2;0;128;0;48;2;248;248;248mdef\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;255;48;2;248;248;248mloop_first_last\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalues\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mIterable\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m[\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mT\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m]\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m-\x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m>\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mIterable\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m[\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mTuple\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m[\x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248mb\x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[3;38;2;186;33;33;48;2;248;248;248m"""Iterate and generate a tuple with a flag for first an\x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248miter\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalues\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mtry\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248mnext\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mexcept\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;210;65;58;48;2;248;248;248mStopIteration\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mreturn\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mTrue\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mfor\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalue\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;170;34;255;48;2;248;248;248min\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248myield\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mFalse\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mFalse\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalue\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248myield\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mTrue\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[48;2;248;248;248m \x1b[0m\n' + assert rendered_syntax == expected + + def test_python_render_simple_indent_guides(): syntax = Syntax( CODE, From 0a27887ff1fe2feffba2d7d9aea88f651bb3ed7a Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Thu, 9 Dec 2021 19:17:09 +0000 Subject: [PATCH 2/9] Fix typing --- rich/syntax.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rich/syntax.py b/rich/syntax.py index 4ef751e84..fe31a51d1 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -3,7 +3,7 @@ from rich.containers import Lines import textwrap from abc import ABC, abstractmethod -from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, Union +from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, Union, cast from pygments.lexer import Lexer from pygments.lexers import get_lexer_by_name, guess_lexer_for_filename @@ -382,7 +382,7 @@ def highlight( _get_theme_style = self._theme.get_style_for_token try: lexer = self.lexer or get_lexer_by_name( - self.lexer_name, + cast(str, self.lexer_name), stripnl=False, ensurenl=True, tabsize=self.tab_size, From 5ab8b9fa1de567c2529f34b70f0ca8e06947b09b Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Sat, 11 Dec 2021 22:03:06 +0000 Subject: [PATCH 3/9] Simplify check for lexer --- rich/syntax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/syntax.py b/rich/syntax.py index fe31a51d1..3a2976271 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -243,7 +243,7 @@ def __init__( background_color: Optional[str] = None, indent_guides: bool = False, ) -> None: - if all((lexer_name, lexer)): + if lexer_name and lexer: raise ValueError("Cannot pass both lexer_name and lexer") self.code = code From 2d5675b71a276bab54bec9072a5d4aaf332126b2 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Sat, 11 Dec 2021 22:03:17 +0000 Subject: [PATCH 4/9] Split lexer check --- rich/syntax.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/rich/syntax.py b/rich/syntax.py index 3a2976271..6c51681e7 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -381,12 +381,17 @@ def highlight( ) _get_theme_style = self._theme.get_style_for_token try: - lexer = self.lexer or get_lexer_by_name( - cast(str, self.lexer_name), - stripnl=False, - ensurenl=True, - tabsize=self.tab_size, - ) + if self.lexer_name: + lexer = get_lexer_by_name( + self.lexer_name, + stripnl=False, + ensurenl=True, + tabsize=self.tab_size, + ) + else: + assert self.lexer + + lexer = self.lexer except ClassNotFound: text.append(code) else: From 17ba9574a4c34f936b36150182ee4a8a2c0e1bc5 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Sat, 11 Dec 2021 22:05:38 +0000 Subject: [PATCH 5/9] Remove unused import --- rich/syntax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/syntax.py b/rich/syntax.py index 6c51681e7..aa5826b50 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -3,7 +3,7 @@ from rich.containers import Lines import textwrap from abc import ABC, abstractmethod -from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, Union, cast +from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, Union from pygments.lexer import Lexer from pygments.lexers import get_lexer_by_name, guess_lexer_for_filename From 6e930a30c3caf3c1e4f7c92f9114e27b7334773f Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Sat, 11 Dec 2021 22:15:47 +0000 Subject: [PATCH 6/9] Add myself to contributors --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1551e3657..5aaf87765 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -25,3 +25,4 @@ The following people have contributed to the development of Rich: - [Tim Savage](https://github.com/timsavage) - [Nicolas Simonds](https://github.com/0xDEC0DE) - [Gabriele N. Tornetta](https://github.com/p403n1x87) +- [Patrick Arminio](https://github.com/patrick91) From 6c2510ed115f233510c49a8edc81fdba0469c296 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Sun, 12 Dec 2021 12:31:40 +0000 Subject: [PATCH 7/9] Use only one argument for passing a lexer --- rich/syntax.py | 41 ++++++++++++++++++++--------------------- tests/test_syntax.py | 40 ++++++++++++++-------------------------- 2 files changed, 34 insertions(+), 47 deletions(-) diff --git a/rich/syntax.py b/rich/syntax.py index aa5826b50..05ebdf9aa 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -195,8 +195,7 @@ class Syntax(JupyterMixin): Args: code (str): Code to highlight. - lexer_name (str): Lexer to use (see https://pygments.org/docs/lexers/) - lexer (Lexer): Lexer instance to use (see https://pygments.org/docs/lexers/) + lexer (Lexer | str): Lexer to use (see https://pygments.org/docs/lexers/) theme (str, optional): Color theme, aka Pygments style (see https://pygments.org/docs/styles/#getting-a-list-of-available-styles). Defaults to "monokai". dedent (bool, optional): Enable stripping of initial whitespace. Defaults to False. line_numbers (bool, optional): Enable rendering of line numbers. Defaults to False. @@ -228,9 +227,8 @@ def get_theme(cls, name: Union[str, SyntaxTheme]) -> SyntaxTheme: def __init__( self, code: str, - lexer_name: Optional[str] = None, + lexer: Union[Lexer, str], *, - lexer: Optional[Lexer] = None, theme: Union[str, SyntaxTheme] = DEFAULT_THEME, dedent: bool = False, line_numbers: bool = False, @@ -243,12 +241,8 @@ def __init__( background_color: Optional[str] = None, indent_guides: bool = False, ) -> None: - if lexer_name and lexer: - raise ValueError("Cannot pass both lexer_name and lexer") - self.code = code - self.lexer_name = lexer_name - self.lexer = lexer + self._lexer = lexer self.dedent = dedent self.line_numbers = line_numbers self.start_line = start_line @@ -355,6 +349,20 @@ def _get_token_color(self, token_type: TokenType) -> Optional[Color]: style = self._theme.get_style_for_token(token_type) return style.color + @property + def lexer(self) -> Optional[Lexer]: + if isinstance(self._lexer, Lexer): + return self._lexer + try: + return get_lexer_by_name( + self._lexer, + stripnl=False, + ensurenl=True, + tabsize=self.tab_size, + ) + except ClassNotFound: + return None + def highlight( self, code: str, line_range: Optional[Tuple[int, int]] = None ) -> Text: @@ -380,19 +388,10 @@ def highlight( no_wrap=not self.word_wrap, ) _get_theme_style = self._theme.get_style_for_token - try: - if self.lexer_name: - lexer = get_lexer_by_name( - self.lexer_name, - stripnl=False, - ensurenl=True, - tabsize=self.tab_size, - ) - else: - assert self.lexer - lexer = self.lexer - except ClassNotFound: + lexer = self.lexer + + if lexer is None: text.append(code) else: if line_range: diff --git a/tests/test_syntax.py b/tests/test_syntax.py index 3f8e5d3d4..de739c8d8 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -29,23 +29,10 @@ def loop_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]: yield first, True, previous_value''' -def test_cannot_pass_both_lexer_name_and_lexer(): - code = "\n\nimport this\n\n" - with pytest.raises(ValueError, match="Cannot pass both lexer_name and lexer"): - Syntax( - code, - lexer_name="python", - lexer=PythonLexer, - theme="ascii_light", - code_width=30, - line_numbers=True, - ) - - def test_blank_lines(): code = "\n\nimport this\n\n" syntax = Syntax( - code, lexer_name="python", theme="ascii_light", code_width=30, line_numbers=True + code, lexer="python", theme="ascii_light", code_width=30, line_numbers=True ) result = render(syntax) print(repr(result)) @@ -59,7 +46,7 @@ def test_python_render(): syntax = Panel.fit( Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=True, line_range=(2, 10), theme="foo", @@ -77,7 +64,7 @@ def test_python_render(): def test_python_render_simple(): syntax = Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=False, theme="foo", code_width=60, @@ -107,7 +94,7 @@ def test_python_render_simple_passing_lexer_instance(): def test_python_render_simple_indent_guides(): syntax = Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=False, theme="ansi_light", code_width=60, @@ -123,7 +110,7 @@ def test_python_render_simple_indent_guides(): def test_python_render_line_range_indent_guides(): syntax = Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=False, theme="ansi_light", code_width=60, @@ -141,7 +128,7 @@ def test_python_render_indent_guides(): syntax = Panel.fit( Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=True, line_range=(2, 10), theme="foo", @@ -174,7 +161,7 @@ def test_get_line_color_none(): style._background_style = Style(bgcolor=None) syntax = Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=True, line_range=(2, 10), theme=style, @@ -188,7 +175,7 @@ def test_get_line_color_none(): def test_highlight_background_color(): syntax = Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=True, line_range=(2, 10), theme="foo", @@ -219,7 +206,7 @@ def test_get_style_for_token(): style._style_cache = style_dict syntax = Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=True, line_range=(2, 10), theme=style, @@ -233,7 +220,7 @@ def test_get_style_for_token(): def test_option_no_wrap(): syntax = Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=True, line_range=(2, 10), code_width=60, @@ -260,7 +247,8 @@ def test_from_file(): try: os.write(fh, b"import this\n") syntax = Syntax.from_path(path) - assert syntax.lexer_name == "Python" + assert syntax.lexer + assert syntax.lexer.name == "Python" assert syntax.code == "import this\n" finally: os.remove(path) @@ -272,7 +260,7 @@ def test_from_file_unknown_lexer(): try: os.write(fh, b"import this\n") syntax = Syntax.from_path(path) - assert syntax.lexer_name == "default" + assert syntax.lexer is None assert syntax.code == "import this\n" finally: os.remove(path) @@ -282,7 +270,7 @@ def test_from_file_unknown_lexer(): syntax = Panel.fit( Syntax( CODE, - lexer_name="python", + lexer="python", line_numbers=True, line_range=(2, 10), theme="foo", From a8ae7b5c1e2633d1572390ae313b118b7413116f Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Fri, 31 Dec 2021 13:26:43 +0100 Subject: [PATCH 8/9] Fix for mypy --- rich/syntax.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rich/syntax.py b/rich/syntax.py index 05ebdf9aa..7dd5922a3 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -401,6 +401,8 @@ def highlight( def line_tokenize() -> Iterable[Tuple[Any, str]]: """Split tokens to one per line.""" + assert lexer + for token_type, token in lexer.get_tokens(code): while token: line_token, new_line, token = token.partition("\n") @@ -709,7 +711,7 @@ def __rich_console__( code = sys.stdin.read() syntax = Syntax( code=code, - lexer_name=args.lexer_name, + lexer=args.lexer_name, line_numbers=args.line_numbers, word_wrap=args.word_wrap, theme=args.theme, From de7ed16f71b54ab4ddc7d40ce67f918dfb9b5180 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Fri, 31 Dec 2021 13:29:26 +0100 Subject: [PATCH 9/9] Add docstring --- rich/syntax.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rich/syntax.py b/rich/syntax.py index 7dd5922a3..759351907 100644 --- a/rich/syntax.py +++ b/rich/syntax.py @@ -351,6 +351,11 @@ def _get_token_color(self, token_type: TokenType) -> Optional[Color]: @property def lexer(self) -> Optional[Lexer]: + """The lexer for this syntax, or None if no lexer was found. + + Tries to find the lexer by name if a string was passed to the constructor. + """ + if isinstance(self._lexer, Lexer): return self._lexer try: