diff options
author | Pradyun Gedam <pgedam@bloomberg.net> | 2022-04-22 15:46:11 +0100 |
---|---|---|
committer | Pradyun Gedam <pgedam@bloomberg.net> | 2022-04-22 15:50:29 +0100 |
commit | 377d642384befe47e96e87550d9a12cbe8f13413 (patch) | |
tree | d474fe20cb825df21cb0988dc973facc73ab02d0 /src/pip/_vendor/rich/syntax.py | |
parent | dfcac4add2801ea078f976b8fba3b24fa246c1ce (diff) | |
download | pip-377d642384befe47e96e87550d9a12cbe8f13413.tar.gz |
Upgrade rich to 12.2.0
Diffstat (limited to 'src/pip/_vendor/rich/syntax.py')
-rw-r--r-- | src/pip/_vendor/rich/syntax.py | 96 |
1 files changed, 65 insertions, 31 deletions
diff --git a/src/pip/_vendor/rich/syntax.py b/src/pip/_vendor/rich/syntax.py index 58cc1037f..089ebfcd1 100644 --- a/src/pip/_vendor/rich/syntax.py +++ b/src/pip/_vendor/rich/syntax.py @@ -1,6 +1,5 @@ import os.path import platform -from pip._vendor.rich.containers import Lines import textwrap from abc import ABC, abstractmethod from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, Union @@ -23,6 +22,8 @@ from pip._vendor.pygments.token import ( ) from pip._vendor.pygments.util import ClassNotFound +from pip._vendor.rich.containers import Lines + from ._loop import loop_first from .color import Color, blend_rgb from .console import Console, ConsoleOptions, JustifyMethod, RenderResult @@ -200,7 +201,8 @@ class Syntax(JupyterMixin): dedent (bool, optional): Enable stripping of initial whitespace. Defaults to False. line_numbers (bool, optional): Enable rendering of line numbers. Defaults to False. start_line (int, optional): Starting number for line numbers. Defaults to 1. - line_range (Tuple[int, int], optional): If given should be a tuple of the start and end line to render. + line_range (Tuple[int | None, int | None], optional): If given should be a tuple of the start and end line to render. + A value of None in the tuple indicates the range is open in that direction. highlight_lines (Set[int]): A set of line numbers to highlight. code_width: Width of code to render (not including line numbers), or ``None`` to use all available width. tab_size (int, optional): Size of tabs. Defaults to 4. @@ -233,7 +235,7 @@ class Syntax(JupyterMixin): dedent: bool = False, line_numbers: bool = False, start_line: int = 1, - line_range: Optional[Tuple[int, int]] = None, + line_range: Optional[Tuple[Optional[int], Optional[int]]] = None, highlight_lines: Optional[Set[int]] = None, code_width: Optional[int] = None, tab_size: int = 4, @@ -264,6 +266,7 @@ class Syntax(JupyterMixin): cls, path: str, encoding: str = "utf-8", + lexer: Optional[Union[Lexer, str]] = None, theme: Union[str, SyntaxTheme] = DEFAULT_THEME, dedent: bool = False, line_numbers: bool = False, @@ -281,6 +284,7 @@ class Syntax(JupyterMixin): Args: path (str): Path to file to highlight. encoding (str): Encoding of file. + lexer (str | Lexer, optional): Lexer to use. If None, lexer will be auto-detected from path/file content. theme (str, optional): Color theme, aka Pygments style (see https://pygments.org/docs/styles/#getting-a-list-of-available-styles). Defaults to "emacs". dedent (bool, optional): Enable stripping of initial whitespace. Defaults to True. line_numbers (bool, optional): Enable rendering of line numbers. Defaults to False. @@ -299,26 +303,12 @@ class Syntax(JupyterMixin): with open(path, "rt", encoding=encoding) as code_file: code = code_file.read() - lexer = None - lexer_name = "default" - try: - _, ext = os.path.splitext(path) - if ext: - extension = ext.lstrip(".").lower() - lexer = get_lexer_by_name(extension) - lexer_name = lexer.name - except ClassNotFound: - pass - - if lexer is None: - try: - lexer_name = guess_lexer_for_filename(path, code).name - except ClassNotFound: - pass + if not lexer: + lexer = cls.guess_lexer(path, code=code) return cls( code, - lexer_name, + lexer, theme=theme, dedent=dedent, line_numbers=line_numbers, @@ -332,6 +322,48 @@ class Syntax(JupyterMixin): indent_guides=indent_guides, ) + @classmethod + def guess_lexer(cls, path: str, code: Optional[str] = None) -> str: + """Guess the alias of the Pygments lexer to use based on a path and an optional string of code. + If code is supplied, it will use a combination of the code and the filename to determine the + best lexer to use. For example, if the file is ``index.html`` and the file contains Django + templating syntax, then "html+django" will be returned. If the file is ``index.html``, and no + templating language is used, the "html" lexer will be used. If no string of code + is supplied, the lexer will be chosen based on the file extension.. + + Args: + path (AnyStr): The path to the file containing the code you wish to know the lexer for. + code (str, optional): Optional string of code that will be used as a fallback if no lexer + is found for the supplied path. + + Returns: + str: The name of the Pygments lexer that best matches the supplied path/code. + """ + lexer: Optional[Lexer] = None + lexer_name = "default" + if code: + try: + lexer = guess_lexer_for_filename(path, code) + except ClassNotFound: + pass + + if not lexer: + try: + _, ext = os.path.splitext(path) + if ext: + extension = ext.lstrip(".").lower() + lexer = get_lexer_by_name(extension) + except ClassNotFound: + pass + + if lexer: + if lexer.aliases: + lexer_name = lexer.aliases[0] + else: + lexer_name = lexer.name + + return lexer_name + def _get_base_style(self) -> Style: """Get the base style.""" default_style = self._theme.get_background_style() + self.background_style @@ -369,7 +401,9 @@ class Syntax(JupyterMixin): return None def highlight( - self, code: str, line_range: Optional[Tuple[int, int]] = None + self, + code: str, + line_range: Optional[Tuple[Optional[int], Optional[int]]] = None, ) -> Text: """Highlight code and return a Text instance. @@ -417,7 +451,7 @@ class Syntax(JupyterMixin): """Convert tokens to spans.""" tokens = iter(line_tokenize()) line_no = 0 - _line_start = line_start - 1 + _line_start = line_start - 1 if line_start else 0 # Skip over tokens until line start while line_no < _line_start: @@ -430,7 +464,7 @@ class Syntax(JupyterMixin): yield (token, _get_theme_style(token_type)) if token.endswith("\n"): line_no += 1 - if line_no >= line_end: + if line_end and line_no >= line_end: break text.append_tokens(tokens_to_spans()) @@ -513,11 +547,6 @@ class Syntax(JupyterMixin): 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) - ends_on_nl = self.code.endswith("\n") code = self.code if ends_on_nl else self.code + "\n" code = textwrap.dedent(code) if self.dedent else code @@ -550,7 +579,7 @@ class Syntax(JupyterMixin): else: syntax_lines = console.render_lines( text, - options.update(width=code_width, height=None), + options.update(width=code_width, height=None, justify="left"), style=self.background_style, pad=True, new_lines=True, @@ -559,6 +588,10 @@ class Syntax(JupyterMixin): 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] @@ -591,7 +624,7 @@ class Syntax(JupyterMixin): if self.word_wrap: wrapped_lines = console.render_lines( line, - render_options.update(height=None), + render_options.update(height=None, justify="left"), style=background_style, pad=not transparent_background, ) @@ -702,7 +735,7 @@ if __name__ == "__main__": # pragma: no cover parser.add_argument( "-x", "--lexer", - default="default", + default=None, dest="lexer_name", help="Lexer name", ) @@ -726,6 +759,7 @@ if __name__ == "__main__": # pragma: no cover else: syntax = Syntax.from_path( args.path, + lexer=args.lexer_name, line_numbers=args.line_numbers, word_wrap=args.word_wrap, theme=args.theme, |