xonsh/xonsh/style_tools.py
pre-commit-ci[bot] 66c0490d37
[pre-commit.ci] pre-commit autoupdate (#5271)
* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/psf/black: 23.12.1 → 24.1.1](https://github.com/psf/black/compare/23.12.1...24.1.1)

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-01-30 12:23:50 +01:00

356 lines
14 KiB
Python

"""Xonsh color styling tools that simulate pygments, when it is unavailable."""
from collections import defaultdict
from xonsh.color_tools import RE_BACKGROUND, iscolor, warn_deprecated_no_color
from xonsh.lazyasd import LazyObject
from xonsh.platform import HAS_PYGMENTS
from xonsh.tools import FORMATTER
class _TokenType(tuple):
"""
Forked from the pygments project
https://bitbucket.org/birkenfeld/pygments-main
Copyright (c) 2006-2017 by the respective authors, All rights reserved.
See https://bitbucket.org/birkenfeld/pygments-main/raw/05818a4ef9891d9ac22c851f7b3ea4b4fce460ab/AUTHORS
"""
parent: "_TokenType|None" = None
def split(self):
buf = []
node = self
while node is not None:
buf.append(node)
node = node.parent
buf.reverse()
return buf
def __init__(self, *args):
# no need to call super.__init__
self.subtypes = set()
def __contains__(self, val):
return self is val or (type(val) is self.__class__ and val[: len(self)] == self)
def __getattr__(self, val):
if not val or not val[0].isupper():
return tuple.__getattribute__(self, val)
new = _TokenType(self + (val,))
setattr(self, val, new)
self.subtypes.add(new)
new.parent = self
return new
def __repr__(self):
return "Token" + (self and "." or "") + ".".join(self)
def __copy__(self):
# These instances are supposed to be singletons
return self
def __deepcopy__(self, memo):
# These instances are supposed to be singletons
return self
Token = _TokenType()
Color = Token.Color
def partial_color_tokenize(template):
"""Tokenizes a template string containing colors. Will return a list
of tuples mapping the token to the string which has that color.
These sub-strings maybe templates themselves.
"""
from xonsh.built_ins import XSH
if HAS_PYGMENTS and XSH.shell is not None:
styles = XSH.shell.shell.styler.styles
elif XSH.shell is not None:
styles = DEFAULT_STYLE_DICT
else:
styles = None
color = Color.RESET
try:
toks, color = _partial_color_tokenize_main(template, styles)
except Exception:
toks = [(Color.RESET, template)]
if styles is not None:
styles[color] # ensure color is available
return toks
def _partial_color_tokenize_main(template, styles):
bopen = "{"
bclose = "}"
colon = ":"
expl = "!"
color = Color.RESET
fg = bg = None
value = ""
toks = []
for literal, field, spec, conv in FORMATTER.parse(template):
if field is None:
value += literal
elif iscolor(field):
value += literal
next_color, fg, bg = color_by_name(field, fg, bg)
if next_color is not color:
if len(value) > 0:
toks.append((color, value))
if styles is not None:
styles[color] # ensure color is available
color = next_color
value = ""
elif field is not None:
parts = [literal, bopen, field]
if conv is not None and len(conv) > 0:
parts.append(expl)
parts.append(conv)
if spec is not None and len(spec) > 0:
parts.append(colon)
parts.append(spec)
parts.append(bclose)
value += "".join(parts)
else:
value += literal
toks.append((color, value))
return toks, color
def color_by_name(name, fg=None, bg=None):
"""Converts a color name to a color token, foreground name,
and background name. Will take into consideration current foreground
and background colors, if provided.
Parameters
----------
name : str
Color name.
fg : str, optional
Foreground color name.
bg : str, optional
Background color name.
Returns
-------
tok : Token
Pygments Token.Color subclass
fg : str or None
New computed foreground color name.
bg : str or None
New computed background color name.
"""
name = name.upper()
if name in ("RESET", "NO_COLOR"):
if name == "NO_COLOR":
warn_deprecated_no_color()
return Color.RESET, None, None
m = RE_BACKGROUND.search(name)
if m is None: # must be foreground color
fg = norm_name(name)
else:
bg = norm_name(name)
# assemble token
if fg is None and bg is None:
tokname = "RESET"
elif fg is None:
tokname = bg
elif bg is None:
tokname = fg
else:
tokname = fg + "__" + bg
tok = getattr(Color, tokname)
return tok, fg, bg
def norm_name(name):
"""Normalizes a color name."""
return name.upper().replace("#", "HEX")
def style_as_faded(template: str) -> str:
"""Remove the colors from the template string and style as faded."""
tokens = partial_color_tokenize(template)
without_color = "".join([str(sect) for _, sect in tokens])
return "{RESET}{#d3d3d3}" + without_color + "{RESET}"
DEFAULT_STYLE_DICT = LazyObject(
lambda: defaultdict(
lambda: "",
{
Token: "",
Token.Color.BACKGROUND_BLACK: "bg:ansiblack",
Token.Color.BACKGROUND_BLUE: "bg:ansiblue",
Token.Color.BACKGROUND_CYAN: "bg:ansicyan",
Token.Color.BACKGROUND_GREEN: "bg:ansigreen",
Token.Color.BACKGROUND_INTENSE_BLACK: "bg:ansibrightblack",
Token.Color.BACKGROUND_INTENSE_BLUE: "bg:ansibrightblue",
Token.Color.BACKGROUND_INTENSE_CYAN: "bg:ansibrightcyan",
Token.Color.BACKGROUND_INTENSE_GREEN: "bg:ansibrightgreen",
Token.Color.BACKGROUND_INTENSE_PURPLE: "bg:ansibrightmagenta",
Token.Color.BACKGROUND_INTENSE_RED: "bg:ansibrightred",
Token.Color.BACKGROUND_INTENSE_WHITE: "bg:ansiwhite",
Token.Color.BACKGROUND_INTENSE_YELLOW: "bg:ansibrightyellow",
Token.Color.BACKGROUND_PURPLE: "bg:ansimagenta",
Token.Color.BACKGROUND_RED: "bg:ansired",
Token.Color.BACKGROUND_WHITE: "bg:ansigray",
Token.Color.BACKGROUND_YELLOW: "bg:ansiyellow",
Token.Color.BLACK: "ansiblack",
Token.Color.BLUE: "ansiblue",
Token.Color.BOLD_BLACK: "bold ansiblack",
Token.Color.BOLD_BLUE: "bold ansiblue",
Token.Color.BOLD_CYAN: "bold ansicyan",
Token.Color.BOLD_GREEN: "bold ansigreen",
Token.Color.BOLD_INTENSE_BLACK: "bold ansibrightblack",
Token.Color.BOLD_INTENSE_BLUE: "bold ansibrightblue",
Token.Color.BOLD_INTENSE_CYAN: "bold ansibrightcyan",
Token.Color.BOLD_INTENSE_GREEN: "bold ansibrightgreen",
Token.Color.BOLD_INTENSE_PURPLE: "bold ansibrightmagenta",
Token.Color.BOLD_INTENSE_RED: "bold ansibrightred",
Token.Color.BOLD_INTENSE_WHITE: "bold ansiwhite",
Token.Color.BOLD_INTENSE_YELLOW: "bold ansibrightyellow",
Token.Color.BOLD_PURPLE: "bold ansimagenta",
Token.Color.BOLD_RED: "bold ansired",
Token.Color.BOLD_UNDERLINE_BLACK: "bold underline ansiblack",
Token.Color.BOLD_UNDERLINE_BLUE: "bold underline ansiblue",
Token.Color.BOLD_UNDERLINE_CYAN: "bold underline ansicyan",
Token.Color.BOLD_UNDERLINE_GREEN: "bold underline ansigreen",
Token.Color.BOLD_UNDERLINE_INTENSE_BLACK: "bold underline ansibrightblack",
Token.Color.BOLD_UNDERLINE_INTENSE_BLUE: "bold underline ansibrightblue",
Token.Color.BOLD_UNDERLINE_INTENSE_CYAN: "bold underline ansibrightcyan",
Token.Color.BOLD_UNDERLINE_INTENSE_GREEN: "bold underline ansibrightgreen",
Token.Color.BOLD_UNDERLINE_INTENSE_PURPLE: "bold underline ansibrightmagenta",
Token.Color.BOLD_UNDERLINE_INTENSE_RED: "bold underline ansibrightred",
Token.Color.BOLD_UNDERLINE_INTENSE_WHITE: "bold underline ansiwhite",
Token.Color.BOLD_UNDERLINE_INTENSE_YELLOW: "bold underline ansibrightyellow",
Token.Color.BOLD_UNDERLINE_PURPLE: "bold underline ansimagenta",
Token.Color.BOLD_UNDERLINE_RED: "bold underline ansired",
Token.Color.BOLD_UNDERLINE_WHITE: "bold underline ansigray",
Token.Color.BOLD_UNDERLINE_YELLOW: "bold underline ansiyellow",
Token.Color.BOLD_WHITE: "bold ansigray",
Token.Color.BOLD_YELLOW: "bold ansiyellow",
Token.Color.CYAN: "ansicyan",
Token.Color.GREEN: "ansigreen",
Token.Color.INTENSE_BLACK: "ansibrightblack",
Token.Color.INTENSE_BLUE: "ansibrightblue",
Token.Color.INTENSE_CYAN: "ansibrightcyan",
Token.Color.INTENSE_GREEN: "ansibrightgreen",
Token.Color.INTENSE_PURPLE: "ansibrightmagenta",
Token.Color.INTENSE_RED: "ansibrightred",
Token.Color.INTENSE_WHITE: "ansiwhite",
Token.Color.INTENSE_YELLOW: "ansibrightyellow",
Token.Color.RESET: "noinherit",
Token.Color.PURPLE: "ansimagenta",
Token.Color.RED: "ansired",
Token.Color.UNDERLINE_BLACK: "underline ansiblack",
Token.Color.UNDERLINE_BLUE: "underline ansiblue",
Token.Color.UNDERLINE_CYAN: "underline ansicyan",
Token.Color.UNDERLINE_GREEN: "underline ansigreen",
Token.Color.UNDERLINE_INTENSE_BLACK: "underline ansibrightblack",
Token.Color.UNDERLINE_INTENSE_BLUE: "underline ansibrightblue",
Token.Color.UNDERLINE_INTENSE_CYAN: "underline ansibrightcyan",
Token.Color.UNDERLINE_INTENSE_GREEN: "underline ansibrightgreen",
Token.Color.UNDERLINE_INTENSE_PURPLE: "underline ansibrightmagenta",
Token.Color.UNDERLINE_INTENSE_RED: "underline ansibrightred",
Token.Color.UNDERLINE_INTENSE_WHITE: "underline ansiwhite",
Token.Color.UNDERLINE_INTENSE_YELLOW: "underline ansibrightyellow",
Token.Color.UNDERLINE_PURPLE: "underline ansimagenta",
Token.Color.UNDERLINE_RED: "underline ansired",
Token.Color.UNDERLINE_WHITE: "underline ansigray",
Token.Color.UNDERLINE_YELLOW: "underline ansiyellow",
Token.Color.WHITE: "ansigray",
Token.Color.YELLOW: "ansiyellow",
Token.Comment: "underline ansicyan",
Token.Comment.Hashbang: "",
Token.Comment.Multiline: "",
Token.Comment.Preproc: "underline ansiyellow",
Token.Comment.PreprocFile: "",
Token.Comment.Single: "",
Token.Comment.Special: "",
Token.Error: "ansibrightred",
Token.Escape: "",
Token.Generic: "",
Token.Generic.Deleted: "ansired",
Token.Generic.Emph: "underline",
Token.Generic.Error: "bold ansibrightred",
Token.Generic.Heading: "bold ansiblue",
Token.Generic.Inserted: "ansibrightgreen",
Token.Generic.Output: "ansiblue",
Token.Generic.Prompt: "bold ansiblue",
Token.Generic.Strong: "",
Token.Generic.Subheading: "bold ansimagenta",
Token.Generic.Traceback: "ansiblue",
Token.Keyword: "bold ansigreen",
Token.Keyword.Constant: "",
Token.Keyword.Declaration: "",
Token.Keyword.Namespace: "",
Token.Keyword.Pseudo: "nobold",
Token.Keyword.Reserved: "",
Token.Keyword.Type: "nobold ansired",
Token.Literal: "",
Token.Literal.Date: "",
Token.Literal.Number: "ansibrightblack",
Token.Literal.Number.Bin: "",
Token.Literal.Number.Float: "",
Token.Literal.Number.Hex: "",
Token.Literal.Number.Integer: "",
Token.Literal.Number.Integer.Long: "",
Token.Literal.Number.Oct: "",
Token.Literal.String: "ansibrightred",
Token.Literal.String.Affix: "",
Token.Literal.String.Backtick: "",
Token.Literal.String.Char: "",
Token.Literal.String.Delimiter: "",
Token.Literal.String.Doc: "underline",
Token.Literal.String.Double: "",
Token.Literal.String.Escape: "bold ansiyellow",
Token.Literal.String.Heredoc: "",
Token.Literal.String.Interpol: "bold ansimagenta",
Token.Literal.String.Other: "ansigreen",
Token.Literal.String.Regex: "ansimagenta",
Token.Literal.String.Single: "",
Token.Literal.String.Symbol: "ansiyellow",
Token.Name: "",
Token.Name.Attribute: "ansibrightyellow",
Token.Name.Builtin: "ansigreen",
Token.Name.Builtin.Pseudo: "",
Token.Name.Class: "bold ansibrightblue",
Token.Name.Constant: "ansired",
Token.Name.Decorator: "ansibrightmagenta",
Token.Name.Entity: "bold ansigray",
Token.Name.Exception: "bold ansibrightred",
Token.Name.Function: "ansibrightblue",
Token.Name.Function.Magic: "",
Token.Name.Label: "ansibrightyellow",
Token.Name.Namespace: "bold ansibrightblue",
Token.Name.Other: "",
Token.Name.Property: "",
Token.Name.Tag: "bold ansigreen",
Token.Name.Variable: "ansiblue",
Token.Name.Variable.Class: "",
Token.Name.Variable.Global: "",
Token.Name.Variable.Instance: "",
Token.Name.Variable.Magic: "",
Token.Operator: "ansibrightblack",
Token.Operator.Word: "bold ansimagenta",
Token.Other: "",
Token.Punctuation: "",
Token.Text: "",
Token.Text.Whitespace: "ansigray",
Token.PTK.Aborting: "ansibrightblack",
Token.PTK.AutoSuggestion: "ansibrightblack",
Token.PTK.CompletionMenu: "bg:ansigray ansiblack",
Token.PTK.CompletionMenu.Completion: "",
Token.PTK.CompletionMenu.Completion.Current: "bg:ansibrightblack ansiwhite",
Token.PTK.Scrollbar.Arrow: "bg:ansiblack ansiwhite bold",
Token.PTK.Scrollbar.Background: "bg:ansibrightblack",
Token.PTK.Scrollbar.Button: "bg:ansiblack",
},
),
globals(),
"DEFAULT_STYLE_DICT",
)