text: # -*- coding: utf-8 -*-
  """Hooks for pygments syntax highlighting."""
  import os
  import re
  import sys
  import builtins
  import stat
  from collections import ChainMap
  from collections.abc import MutableMapping
  from keyword import iskeyword
  import typing as tp
  
  from xonsh2.lazyimps import os_listxattr
  
  from pygments.lexer import inherit, bygroups, include
  from pygments.lexers.agile import Python3Lexer
  from pygments.token import (
      Keyword,
      Name,
      Comment,
      String,
      Error,
      Number,
      Operator,
      Generic,
      Whitespace,
      Token,
      Punctuation,
      Text,
      _TokenType,
  )
  from pygments.style import Style
  import pygments.util
  
  from xonsh2.commands_cache import CommandsCache
  from xonsh2.lazyasd import LazyObject, LazyDict, lazyobject
  from xonsh2.tools import (
      ON_WINDOWS,
      intensify_colors_for_cmd_exe,
      ANSICOLOR_NAMES_MAP,
      PTK_NEW_OLD_COLOR_MAP,
      hardcode_colors_for_win10,
      FORMATTER,
  )
  
  from xonsh2.color_tools import (
      RE_BACKGROUND,
      BASE_XONSH_COLORS,
      RE_XONSH_COLOR,
      make_palette,
      find_closest_color,
      iscolor,
      warn_deprecated_no_color,
  )
  from xonsh2.style_tools import norm_name
  from xonsh2.lazyimps import terminal256, html
  from xonsh2.platform import (
      os_environ,
      win_ansi_support,
      ptk_version_info,
      pygments_version_info,
  )
  
  from xonsh2.pygments_cache import get_style_by_name, add_custom_style
  
  from xonsh2.events import events
  
  
  #
  # Colors and Styles
  #
  
  Color = Token.Color  # alias to new color token namespace
  
  
  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"):
          return Color.DEFAULT, 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
  
  
  @lazyobject
  def PYGMENTS_MODIFIERS():
      # pygments doesn't support all modifiers.
      # use None to represent unsupported
      return {
          "BOLD": "bold",
          "FAINT": None,
          "ITALIC": "italic",
          "UNDERLINE": "underline",
          "SLOWBLINK": None,
          "FASTBLINK": None,
          "INVERT": None,
          "CONCEAL": None,
          "STRIKETHROUGH": None,
          "BOLDOFF": None,
          "FAINTOFF": None,
          "ITALICOFF": None,
          "UNDERLINEOFF": None,
          "BLINKOFF": None,
          "INVERTOFF": None,
          "REVEALOFF": None,
          "STRIKETHROUGHOFF": None,
      }
  
  
  def color_name_to_pygments_code(name, styles):
      """Converts a xonsh color name to a pygments color code."""
      token = getattr(Color, norm_name(name))
      if token in styles:
          return styles[token]
      m = RE_XONSH_COLOR.match(name)
      if m is None:
          raise ValueError("{!r} is not a color!".format(name))
      parts = m.groupdict()
      # convert regex match into actual pygments colors
      if parts["reset"] is not None:
          if parts["reset"] == "NO_COLOR":
              warn_deprecated_no_color()
          res = "noinherit"
      elif parts["bghex"] is not None:
          res = "bg:#" + parts["bghex"][3:]
      elif parts["background"] is not None:
          color = parts["color"]
          if "#" in color:
              fgcolor = color
          else:
              fgcolor = styles[getattr(Color, color)]
          res = "bg:" + fgcolor
      else:
          # have regular, non-background color
          mods = parts["modifiers"]
          if mods is None:
              mods = []
          else:
              mods = mods.strip("_").split("_")
              mods = [PYGMENTS_MODIFIERS[mod] for mod in mods]
          mods = list(filter(None, mods))  # remove unsupported entries
          color = parts["color"]
          if "#" in color:
              mods.append(color)
          else:
              mods.append(styles[getattr(Color, color)])
          res = " ".join(mods)
      styles[token] = res
      return res
  
  
  def code_by_name(name, styles):
      """Converts a token name into a pygments-style color code.
  
      Parameters
      ----------
      name : str
          Color token name.
      styles : Mapping
          Mapping for looking up non-hex colors
  
      Returns
      -------
      code : str
          Pygments style color code.
      """
      fg, _, bg = name.upper().replace("HEX", "#").partition("__")
      if fg.startswith("BACKGROUND_") or fg.startswith("BG#"):
          # swap fore & back if needed.
          fg, bg = bg, fg
      # convert names to codes
      if len(fg) == 0 and len(bg) == 0:
          code = "noinherit"
      elif len(fg) == 0:
          code = color_name_to_pygments_code(bg, styles)
      elif len(bg) == 0:
          code = color_name_to_pygments_code(fg, styles)
      else:
          # have both colors
          code = color_name_to_pygments_code(bg, styles)
          code += " "
          code += color_name_to_pygments_code(fg, styles)
      return code
  
  
  def color_token_by_name(xc: tuple, styles=None) -> _TokenType:
      """Returns (color) token corresponding to Xonsh color tuple, side effect: defines token is defined in styles"""
      if not styles:
          try:
              styles = builtins.__xonsh__.shell.shell.styler.styles  # type:ignore
          except AttributeError:
              return Color
  
      tokName = xc[0]
      pc = color_name_to_pygments_code(xc[0], styles)
  
      if len(xc) > 1:
          pc += " " + color_name_to_pygments_code(xc[1], styles)
          tokName += "__" + xc[1]
  
      token = getattr(Color, norm_name(tokName))
      if token not in styles:
          styles[token] = pc
      return token
  
  
  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.
      """
      if builtins.__xonsh__.shell is not None:
          styles = __xonsh__.shell.shell.styler.styles
      else:
          styles = None
      color = Color.DEFAULT
      try:
          toks, color = _partial_color_tokenize_main(template, styles)
      except Exception:
          toks = [(Color.DEFAULT, 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.DEFAULT
      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
  
  
  class CompoundColorMap(MutableMapping):
      """Looks up color tokens by name, potentially generating the value
      from the lookup.
      """
  
      def __init__(self, styles, *args, **kwargs):
          self.styles = styles
          self.colors = dict(*args, **kwargs)
  
      def __getitem__(self, key):
          if key in self.colors:
              return self.colors[key]
          if key in self.styles:
              value = self.styles[key]
              self[key] = value
              return value
          if key is Color:
              raise KeyError
          pre, _, name = str(key).rpartition(".")
          if pre != "Token.Color":
              raise KeyError
          value = code_by_name(name, self.styles)
          self[key] = value
          return value
  
      def __setitem__(self, key, value):
          self.colors[key] = value
  
      def __delitem__(self, key):
          del self.colors[key]
  
      def __iter__(self):
          yield from self.colors.keys()
  
      def __len__(self):
          return len(self.colors)
  
  
  class XonshStyle(Style):
      """A xonsh pygments style that will dispatch to the correct color map
      by using a ChainMap.  The style_name property may be used to reset
      the current style.
      """
  
      def __init__(self, style_name="default"):
          """
          Parameters
          ----------
          style_name : str, optional
              The style name to initialize with.
          """
          self.trap = {}  # for trapping custom colors set by user
          self._smap = {}
          self._style_name = ""
          self.style_name = style_name
          super().__init__()
  
      @property
      def style_name(self):
          return self._style_name
  
      @style_name.setter
      def style_name(self, value):
          if self._style_name == value:
              return
          if value not in STYLES:
              try:  # loading style dynamically
                  pygments_style_by_name(value)
              except Exception:
                  print(
                      "Could not find style {0!r}, using default".format(value),
                      file=sys.stderr,
                  )
                  value = "default"
                  builtins.__xonsh__.env["XONSH_COLOR_STYLE"] = value
          cmap = STYLES[value]
          if value == "default":
              self._smap = XONSH_BASE_STYLE.copy()
          else:
              try:
                  style_obj = get_style_by_name(value)()
                  self._smap = style_obj.styles.copy()
                  self.highlight_color = style_obj.highlight_color
                  self.background_color = style_obj.background_color
              except (ImportError, pygments.util.ClassNotFound):
                  self._smap = XONSH_BASE_STYLE.copy()
          compound = CompoundColorMap(ChainMap(self.trap, cmap, PTK_STYLE, self._smap))
          self.styles = ChainMap(self.trap, cmap, PTK_STYLE, self._smap, compound)
          self._style_name = value
  
          for file_type, xonsh_color in builtins.__xonsh__.env.get(
              "LS_COLORS", {}
          ).items():
              color_token = color_token_by_name(xonsh_color, self.styles)
              file_color_tokens[file_type] = color_token
  
          if ON_WINDOWS and "prompt_toolkit" in builtins.__xonsh__.shell.shell_type:
              self.enhance_colors_for_cmd_exe()
  
      @style_name.deleter
      def style_name(self):
          self._style_name = ""
  
      def enhance_colors_for_cmd_exe(self):
          """ Enhance colors when using cmd.exe on windows.
              When using the default style all blue and dark red colors
              are changed to CYAN and intense red.
          """
          env = builtins.__xonsh__.env
          # Ensure we are not using the new Windows Terminal, ConEmu or Visual Stuio Code
          if "WT_SESSION" in env or "CONEMUANSI" in env or "VSCODE_PID" in env:
              return
          if env.get("INTENSIFY_COLORS_ON_WIN", False):
              if win_ansi_support():
                  newcolors = hardcode_colors_for_win10(self.styles)
              else:
                  newcolors = intensify_colors_for_cmd_exe(self.styles)
              self.trap.update(newcolors)
  
  
  def xonsh_style_proxy(styler):
      """Factory for a proxy class to a xonsh style."""
      # Monky patch pygments' list of known ansi colors
      # with the new ansi color names used by PTK2
      # Can be removed once pygment names get fixed.
      if pygments_version_info() and pygments_version_info() < (2, 4, 0):
          pygments.style.ansicolors.update(ANSICOLOR_NAMES_MAP)
  
      class XonshStyleProxy(Style):
          """Simple proxy class to fool prompt toolkit."""
  
          target = styler
          styles = styler.styles
          highlight_color = styler.highlight_color
          background_color = styler.background_color
  
          def __new__(cls, *args, **kwargs):
              return cls.target
  
      return XonshStyleProxy
  
  
  def _get_token_by_name(name):
      """Get pygments token object by its string representation."""
      token = Token
      parts = name.split(".")
  
      if len(parts) == 1:
          parts = ["Color"] + parts
  
      if parts[0] == "Token":
          parts = parts[1:]
  
      while len(parts):
          token = getattr(token, parts[0])
          parts = parts[1:]
  
      return token
  
  
  def register_custom_pygments_style(
      name, styles, highlight_color=None, background_color=None, base="default"
  ):
      """Register custom style.
  
      Parameters
      ----------
      name : str
          Style name.
      styles : dict
          Token -> style mapping.
      highlight_color : str
          Hightlight color.
      background_color : str
          Background color.
      base : str, optional
          Base style to use as default.
  
      Returns
      -------
      style : The ``pygments.Style`` subclass created
      """
      base_style = get_style_by_name(base)
      custom_styles = base_style.styles.copy()
  
      for token, value in styles.items():
          if isinstance(token, str):
              token = _get_token_by_name(token)
          custom_styles[token] = value
  
      style = type(
          f"Custom{name}Style",
          (Style,),
          {
              "styles": custom_styles,
              "highlight_color": highlight_color
              if highlight_color is not None
              else base_style.highlight_color,
              "background_color": background_color
              if background_color is not None
              else base_style.background_color,
          },
      )
  
      add_custom_style(name, style)
  
      cmap = pygments_style_by_name(base).copy()
  
      # replace colors in color map if found in styles
      for token in cmap.keys():
          if token in custom_styles:
              cmap[token] = custom_styles[token]
  
      STYLES[name] = cmap
  
      return style
  
  
  PTK_STYLE = LazyObject(
      lambda: {
          Token.Menu.Completions: "bg:ansigray ansiblack",
          Token.Menu.Completions.Completion: "",
          Token.Menu.Completions.Completion.Current: "bg:ansibrightblack ansiwhite",
          Token.Scrollbar: "bg:ansibrightblack",
          Token.Scrollbar.Button: "bg:ansiblack",
          Token.Scrollbar.Arrow: "bg:ansiblack ansiwhite bold",
          Token.AutoSuggestion: "ansibrightblack",
          Token.Aborted: "ansibrightblack",
      },
      globals(),
      "PTK_STYLE",
  )
  
  
  XONSH_BASE_STYLE = LazyObject(
      lambda: {
          Whitespace: "ansigray",
          Comment: "underline ansicyan",
          Comment.Preproc: "underline ansiyellow",
          Keyword: "bold ansigreen",
          Keyword.Pseudo: "nobold",
          Keyword.Type: "nobold ansired",
          Operator: "ansibrightblack",
          Operator.Word: "bold ansimagenta",
          Name.Builtin: "ansigreen",
          Name.Function: "ansibrightblue",
          Name.Class: "bold ansibrightblue",
          Name.Namespace: "bold ansibrightblue",
          Name.Exception: "bold ansibrightred",
          Name.Variable: "ansiblue",
          Name.Constant: "ansired",
          Name.Label: "ansibrightyellow",
          Name.Entity: "bold ansigray",
          Name.Attribute: "ansibrightyellow",
          Name.Tag: "bold ansigreen",
          Name.Decorator: "ansibrightmagenta",
          String: "ansibrightred",
          String.Doc: "underline",
          String.Interpol: "bold ansimagenta",
          String.Escape: "bold ansiyellow",
          String.Regex: "ansimagenta",
          String.Symbol: "ansiyellow",
          String.Other: "ansigreen",
          Number: "ansibrightblack",
          Generic.Heading: "bold ansiblue",
          Generic.Subheading: "bold ansimagenta",
          Generic.Deleted: "ansired",
          Generic.Inserted: "ansibrightgreen",
          Generic.Error: "bold ansibrightred",
          Generic.Emph: "underline",
          Generic.Prompt: "bold ansiblue",
          Generic.Output: "ansiblue",
          Generic.Traceback: "ansiblue",
          Error: "ansibrightred",
      },
      globals(),
      "XONSH_BASE_STYLE",
  )
  
  
  def _bw_style():
      style = {
          Color.BLACK: "noinherit",
          Color.BLUE: "noinherit",
          Color.CYAN: "noinherit",
          Color.GREEN: "noinherit",
          Color.INTENSE_BLACK: "noinherit",
          Color.INTENSE_BLUE: "noinherit",
          Color.INTENSE_CYAN: "noinherit",
          Color.INTENSE_GREEN: "noinherit",
          Color.INTENSE_PURPLE: "noinherit",
          Color.INTENSE_RED: "noinherit",
          Color.INTENSE_WHITE: "noinherit",
          Color.INTENSE_YELLOW: "noinherit",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "noinherit",
          Color.RED: "noinherit",
          Color.WHITE: "noinherit",
          Color.YELLOW: "noinherit",
      }
      return style
  
  
  def _default_style():
      style = {
          Color.BLACK: "ansiblack",
          Color.BLUE: "ansiblue",
          Color.CYAN: "ansicyan",
          Color.GREEN: "ansigreen",
          Color.INTENSE_BLACK: "ansibrightblack",
          Color.INTENSE_BLUE: "ansibrightblue",
          Color.INTENSE_CYAN: "ansibrightcyan",
          Color.INTENSE_GREEN: "ansibrightgreen",
          Color.INTENSE_PURPLE: "ansibrightmagenta",
          Color.INTENSE_RED: "ansibrightred",
          Color.INTENSE_WHITE: "ansiwhite",
          Color.INTENSE_YELLOW: "ansibrightyellow",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "ansimagenta",
          Color.RED: "ansired",
          Color.WHITE: "ansigray",
          Color.YELLOW: "ansiyellow",
      }
      return style
  
  
  def _monokai_style():
      style = {
          Color.BLACK: "#1e0010",
          Color.BLUE: "#6666ef",
          Color.CYAN: "#66d9ef",
          Color.GREEN: "#2ee22e",
          Color.INTENSE_BLACK: "#5e5e5e",
          Color.INTENSE_BLUE: "#2626d7",
          Color.INTENSE_CYAN: "#2ed9d9",
          Color.INTENSE_GREEN: "#a6e22e",
          Color.INTENSE_PURPLE: "#ae81ff",
          Color.INTENSE_RED: "#f92672",
          Color.INTENSE_WHITE: "#f8f8f2",
          Color.INTENSE_YELLOW: "#e6db74",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#960050",
          Color.RED: "#AF0000",
          Color.WHITE: "#d7d7d7",
          Color.YELLOW: "#e2e22e",
      }
      return style
  
  
  ######################################
  #   Auto-generated below this line   #
  ######################################
  def _algol_style():
      style = {
          Color.BLACK: "#666",
          Color.BLUE: "#666",
          Color.CYAN: "#666",
          Color.GREEN: "#666",
          Color.INTENSE_BLACK: "#666",
          Color.INTENSE_BLUE: "#888",
          Color.INTENSE_CYAN: "#888",
          Color.INTENSE_GREEN: "#888",
          Color.INTENSE_PURPLE: "#888",
          Color.INTENSE_RED: "#FF0000",
          Color.INTENSE_WHITE: "#888",
          Color.INTENSE_YELLOW: "#888",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#666",
          Color.RED: "#FF0000",
          Color.WHITE: "#888",
          Color.YELLOW: "#FF0000",
      }
      return style
  
  
  def _algol_nu_style():
      style = {
          Color.BLACK: "#666",
          Color.BLUE: "#666",
          Color.CYAN: "#666",
          Color.GREEN: "#666",
          Color.INTENSE_BLACK: "#666",
          Color.INTENSE_BLUE: "#888",
          Color.INTENSE_CYAN: "#888",
          Color.INTENSE_GREEN: "#888",
          Color.INTENSE_PURPLE: "#888",
          Color.INTENSE_RED: "#FF0000",
          Color.INTENSE_WHITE: "#888",
          Color.INTENSE_YELLOW: "#888",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#666",
          Color.RED: "#FF0000",
          Color.WHITE: "#888",
          Color.YELLOW: "#FF0000",
      }
      return style
  
  
  def _autumn_style():
      style = {
          Color.BLACK: "#000080",
          Color.BLUE: "#0000aa",
          Color.CYAN: "#00aaaa",
          Color.GREEN: "#00aa00",
          Color.INTENSE_BLACK: "#555555",
          Color.INTENSE_BLUE: "#1e90ff",
          Color.INTENSE_CYAN: "#1e90ff",
          Color.INTENSE_GREEN: "#4c8317",
          Color.INTENSE_PURPLE: "#FAA",
          Color.INTENSE_RED: "#aa5500",
          Color.INTENSE_WHITE: "#bbbbbb",
          Color.INTENSE_YELLOW: "#FAA",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#800080",
          Color.RED: "#aa0000",
          Color.WHITE: "#aaaaaa",
          Color.YELLOW: "#aa5500",
      }
      return style
  
  
  def _borland_style():
      style = {
          Color.BLACK: "#000000",
          Color.BLUE: "#000080",
          Color.CYAN: "#008080",
          Color.GREEN: "#008800",
          Color.INTENSE_BLACK: "#555555",
          Color.INTENSE_BLUE: "#0000FF",
          Color.INTENSE_CYAN: "#ddffdd",
          Color.INTENSE_GREEN: "#888888",
          Color.INTENSE_PURPLE: "#e3d2d2",
          Color.INTENSE_RED: "#FF0000",
          Color.INTENSE_WHITE: "#ffdddd",
          Color.INTENSE_YELLOW: "#e3d2d2",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#800080",
          Color.RED: "#aa0000",
          Color.WHITE: "#aaaaaa",
          Color.YELLOW: "#a61717",
      }
      return style
  
  
  def _colorful_style():
      style = {
          Color.BLACK: "#000",
          Color.BLUE: "#00C",
          Color.CYAN: "#0e84b5",
          Color.GREEN: "#00A000",
          Color.INTENSE_BLACK: "#555",
          Color.INTENSE_BLUE: "#33B",
          Color.INTENSE_CYAN: "#bbbbbb",
          Color.INTENSE_GREEN: "#888",
          Color.INTENSE_PURPLE: "#FAA",
          Color.INTENSE_RED: "#D42",
          Color.INTENSE_WHITE: "#fff0ff",
          Color.INTENSE_YELLOW: "#FAA",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#800080",
          Color.RED: "#A00000",
          Color.WHITE: "#bbbbbb",
          Color.YELLOW: "#A60",
      }
      return style
  
  
  def _emacs_style():
      style = {
          Color.BLACK: "#008000",
          Color.BLUE: "#000080",
          Color.CYAN: "#04D",
          Color.GREEN: "#00A000",
          Color.INTENSE_BLACK: "#666666",
          Color.INTENSE_BLUE: "#04D",
          Color.INTENSE_CYAN: "#bbbbbb",
          Color.INTENSE_GREEN: "#00BB00",
          Color.INTENSE_PURPLE: "#AA22FF",
          Color.INTENSE_RED: "#D2413A",
          Color.INTENSE_WHITE: "#bbbbbb",
          Color.INTENSE_YELLOW: "#bbbbbb",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#800080",
          Color.RED: "#A00000",
          Color.WHITE: "#bbbbbb",
          Color.YELLOW: "#BB6622",
      }
      return style
  
  
  def _friendly_style():
      style = {
          Color.BLACK: "#007020",
          Color.BLUE: "#000080",
          Color.CYAN: "#0e84b5",
          Color.GREEN: "#00A000",
          Color.INTENSE_BLACK: "#555555",
          Color.INTENSE_BLUE: "#70a0d0",
          Color.INTENSE_CYAN: "#60add5",
          Color.INTENSE_GREEN: "#40a070",
          Color.INTENSE_PURPLE: "#bb60d5",
          Color.INTENSE_RED: "#d55537",
          Color.INTENSE_WHITE: "#fff0f0",
          Color.INTENSE_YELLOW: "#bbbbbb",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#800080",
          Color.RED: "#A00000",
          Color.WHITE: "#bbbbbb",
          Color.YELLOW: "#c65d09",
      }
      return style
  
  
  def _fruity_style():
      style = {
          Color.BLACK: "#0f140f",
          Color.BLUE: "#0086d2",
          Color.CYAN: "#0086d2",
          Color.GREEN: "#008800",
          Color.INTENSE_BLACK: "#444444",
          Color.INTENSE_BLUE: "#0086f7",
          Color.INTENSE_CYAN: "#0086f7",
          Color.INTENSE_GREEN: "#888888",
          Color.INTENSE_PURPLE: "#ff0086",
          Color.INTENSE_RED: "#fb660a",
          Color.INTENSE_WHITE: "#ffffff",
          Color.INTENSE_YELLOW: "#cdcaa9",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#ff0086",
          Color.RED: "#ff0007",
          Color.WHITE: "#cdcaa9",
          Color.YELLOW: "#fb660a",
      }
      return style
  
  
  def _igor_style():
      style = {
          Color.BLACK: "#009C00",
          Color.BLUE: "#0000FF",
          Color.CYAN: "#007575",
          Color.GREEN: "#009C00",
          Color.INTENSE_BLACK: "#007575",
          Color.INTENSE_BLUE: "#0000FF",
          Color.INTENSE_CYAN: "#007575",
          Color.INTENSE_GREEN: "#009C00",
          Color.INTENSE_PURPLE: "#CC00A3",
          Color.INTENSE_RED: "#C34E00",
          Color.INTENSE_WHITE: "#CC00A3",
          Color.INTENSE_YELLOW: "#C34E00",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#CC00A3",
          Color.RED: "#C34E00",
          Color.WHITE: "#CC00A3",
          Color.YELLOW: "#C34E00",
      }
      return style
  
  
  def _lovelace_style():
      style = {
          Color.BLACK: "#444444",
          Color.BLUE: "#2838b0",
          Color.CYAN: "#289870",
          Color.GREEN: "#388038",
          Color.INTENSE_BLACK: "#666666",
          Color.INTENSE_BLUE: "#2838b0",
          Color.INTENSE_CYAN: "#888888",
          Color.INTENSE_GREEN: "#289870",
          Color.INTENSE_PURPLE: "#a848a8",
          Color.INTENSE_RED: "#b83838",
          Color.INTENSE_WHITE: "#888888",
          Color.INTENSE_YELLOW: "#a89028",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#a848a8",
          Color.RED: "#c02828",
          Color.WHITE: "#888888",
          Color.YELLOW: "#b85820",
      }
      return style
  
  
  def _manni_style():
      style = {
          Color.BLACK: "#000000",
          Color.BLUE: "#000099",
          Color.CYAN: "#009999",
          Color.GREEN: "#00CC00",
          Color.INTENSE_BLACK: "#555555",
          Color.INTENSE_BLUE: "#9999FF",
          Color.INTENSE_CYAN: "#00CCFF",
          Color.INTENSE_GREEN: "#99CC66",
          Color.INTENSE_PURPLE: "#CC00FF",
          Color.INTENSE_RED: "#FF6600",
          Color.INTENSE_WHITE: "#FFCCCC",
          Color.INTENSE_YELLOW: "#FFCC33",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#CC00FF",
          Color.RED: "#AA0000",
          Color.WHITE: "#AAAAAA",
          Color.YELLOW: "#CC3300",
      }
      return style
  
  
  def _murphy_style():
      style = {
          Color.BLACK: "#000",
          Color.BLUE: "#000080",
          Color.CYAN: "#0e84b5",
          Color.GREEN: "#00A000",
          Color.INTENSE_BLACK: "#555",
          Color.INTENSE_BLUE: "#66f",
          Color.INTENSE_CYAN: "#5ed",
          Color.INTENSE_GREEN: "#5ed",
          Color.INTENSE_PURPLE: "#e9e",
          Color.INTENSE_RED: "#f84",
          Color.INTENSE_WHITE: "#eee",
          Color.INTENSE_YELLOW: "#fc8",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#800080",
          Color.RED: "#A00000",
          Color.WHITE: "#bbbbbb",
          Color.YELLOW: "#c65d09",
      }
      return style
  
  
  def _native_style():
      style = {
          Color.BLACK: "#520000",
          Color.BLUE: "#3677a9",
          Color.CYAN: "#24909d",
          Color.GREEN: "#589819",
          Color.INTENSE_BLACK: "#666666",
          Color.INTENSE_BLUE: "#447fcf",
          Color.INTENSE_CYAN: "#40ffff",
          Color.INTENSE_GREEN: "#6ab825",
          Color.INTENSE_PURPLE: "#e3d2d2",
          Color.INTENSE_RED: "#cd2828",
          Color.INTENSE_WHITE: "#ffffff",
          Color.INTENSE_YELLOW: "#ed9d13",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#666666",
          Color.RED: "#a61717",
          Color.WHITE: "#aaaaaa",
          Color.YELLOW: "#a61717",
      }
      return style
  
  
  def _paraiso_dark_style():
      style = {
          Color.BLACK: "#776e71",
          Color.BLUE: "#815ba4",
          Color.CYAN: "#06b6ef",
          Color.GREEN: "#48b685",
          Color.INTENSE_BLACK: "#776e71",
          Color.INTENSE_BLUE: "#815ba4",
          Color.INTENSE_CYAN: "#5bc4bf",
          Color.INTENSE_GREEN: "#48b685",
          Color.INTENSE_PURPLE: "#e7e9db",
          Color.INTENSE_RED: "#ef6155",
          Color.INTENSE_WHITE: "#e7e9db",
          Color.INTENSE_YELLOW: "#fec418",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#815ba4",
          Color.RED: "#ef6155",
          Color.WHITE: "#5bc4bf",
          Color.YELLOW: "#f99b15",
      }
      return style
  
  
  def _paraiso_light_style():
      style = {
          Color.BLACK: "#2f1e2e",
          Color.BLUE: "#2f1e2e",
          Color.CYAN: "#06b6ef",
          Color.GREEN: "#48b685",
          Color.INTENSE_BLACK: "#2f1e2e",
          Color.INTENSE_BLUE: "#815ba4",
          Color.INTENSE_CYAN: "#5bc4bf",
          Color.INTENSE_GREEN: "#48b685",
          Color.INTENSE_PURPLE: "#815ba4",
          Color.INTENSE_RED: "#ef6155",
          Color.INTENSE_WHITE: "#5bc4bf",
          Color.INTENSE_YELLOW: "#fec418",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#815ba4",
          Color.RED: "#2f1e2e",
          Color.WHITE: "#8d8687",
          Color.YELLOW: "#f99b15",
      }
      return style
  
  
  def _pastie_style():
      style = {
          Color.BLACK: "#000000",
          Color.BLUE: "#0000DD",
          Color.CYAN: "#0066bb",
          Color.GREEN: "#008800",
          Color.INTENSE_BLACK: "#555555",
          Color.INTENSE_BLUE: "#3333bb",
          Color.INTENSE_CYAN: "#ddffdd",
          Color.INTENSE_GREEN: "#22bb22",
          Color.INTENSE_PURPLE: "#e3d2d2",
          Color.INTENSE_RED: "#dd7700",
          Color.INTENSE_WHITE: "#fff0ff",
          Color.INTENSE_YELLOW: "#e3d2d2",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#bb0066",
          Color.RED: "#aa0000",
          Color.WHITE: "#bbbbbb",
          Color.YELLOW: "#aa6600",
      }
      return style
  
  
  def _perldoc_style():
      style = {
          Color.BLACK: "#000080",
          Color.BLUE: "#000080",
          Color.CYAN: "#1e889b",
          Color.GREEN: "#00aa00",
          Color.INTENSE_BLACK: "#555555",
          Color.INTENSE_BLUE: "#B452CD",
          Color.INTENSE_CYAN: "#bbbbbb",
          Color.INTENSE_GREEN: "#228B22",
          Color.INTENSE_PURPLE: "#B452CD",
          Color.INTENSE_RED: "#CD5555",
          Color.INTENSE_WHITE: "#e3d2d2",
          Color.INTENSE_YELLOW: "#e3d2d2",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#8B008B",
          Color.RED: "#aa0000",
          Color.WHITE: "#a7a7a7",
          Color.YELLOW: "#cb6c20",
      }
      return style
  
  
  def _rrt_style():
      style = {
          Color.BLACK: "#ff0000",
          Color.BLUE: "#87ceeb",
          Color.CYAN: "#87ceeb",
          Color.GREEN: "#00ff00",
          Color.INTENSE_BLACK: "#87ceeb",
          Color.INTENSE_BLUE: "#87ceeb",
          Color.INTENSE_CYAN: "#7fffd4",
          Color.INTENSE_GREEN: "#00ff00",
          Color.INTENSE_PURPLE: "#ee82ee",
          Color.INTENSE_RED: "#ff0000",
          Color.INTENSE_WHITE: "#e5e5e5",
          Color.INTENSE_YELLOW: "#eedd82",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#ee82ee",
          Color.RED: "#ff0000",
          Color.WHITE: "#87ceeb",
          Color.YELLOW: "#ff0000",
      }
      return style
  
  
  def _tango_style():
      style = {
          Color.BLACK: "#000000",
          Color.BLUE: "#0000cf",
          Color.CYAN: "#3465a4",
          Color.GREEN: "#00A000",
          Color.INTENSE_BLACK: "#204a87",
          Color.INTENSE_BLUE: "#5c35cc",
          Color.INTENSE_CYAN: "#f8f8f8",
          Color.INTENSE_GREEN: "#4e9a06",
          Color.INTENSE_PURPLE: "#f8f8f8",
          Color.INTENSE_RED: "#ef2929",
          Color.INTENSE_WHITE: "#f8f8f8",
          Color.INTENSE_YELLOW: "#c4a000",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#800080",
          Color.RED: "#a40000",
          Color.WHITE: "#f8f8f8",
          Color.YELLOW: "#8f5902",
      }
      return style
  
  
  def _trac_style():
      style = {
          Color.BLACK: "#000000",
          Color.BLUE: "#000080",
          Color.CYAN: "#009999",
          Color.GREEN: "#808000",
          Color.INTENSE_BLACK: "#555555",
          Color.INTENSE_BLUE: "#445588",
          Color.INTENSE_CYAN: "#ddffdd",
          Color.INTENSE_GREEN: "#999988",
          Color.INTENSE_PURPLE: "#e3d2d2",
          Color.INTENSE_RED: "#bb8844",
          Color.INTENSE_WHITE: "#ffdddd",
          Color.INTENSE_YELLOW: "#e3d2d2",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#800080",
          Color.RED: "#aa0000",
          Color.WHITE: "#aaaaaa",
          Color.YELLOW: "#808000",
      }
      return style
  
  
  def _vim_style():
      style = {
          Color.BLACK: "#000080",
          Color.BLUE: "#000080",
          Color.CYAN: "#00cdcd",
          Color.GREEN: "#00cd00",
          Color.INTENSE_BLACK: "#666699",
          Color.INTENSE_BLUE: "#3399cc",
          Color.INTENSE_CYAN: "#00cdcd",
          Color.INTENSE_GREEN: "#00cd00",
          Color.INTENSE_PURPLE: "#cd00cd",
          Color.INTENSE_RED: "#FF0000",
          Color.INTENSE_WHITE: "#cccccc",
          Color.INTENSE_YELLOW: "#cdcd00",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#cd00cd",
          Color.RED: "#cd0000",
          Color.WHITE: "#cccccc",
          Color.YELLOW: "#cd0000",
      }
      return style
  
  
  def _vs_style():
      style = {
          Color.BLACK: "#008000",
          Color.BLUE: "#0000ff",
          Color.CYAN: "#2b91af",
          Color.GREEN: "#008000",
          Color.INTENSE_BLACK: "#2b91af",
          Color.INTENSE_BLUE: "#2b91af",
          Color.INTENSE_CYAN: "#2b91af",
          Color.INTENSE_GREEN: "#2b91af",
          Color.INTENSE_PURPLE: "#2b91af",
          Color.INTENSE_RED: "#FF0000",
          Color.INTENSE_WHITE: "#2b91af",
          Color.INTENSE_YELLOW: "#2b91af",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#a31515",
          Color.RED: "#a31515",
          Color.WHITE: "#2b91af",
          Color.YELLOW: "#a31515",
      }
      return style
  
  
  def _xcode_style():
      style = {
          Color.BLACK: "#000000",
          Color.BLUE: "#1C01CE",
          Color.CYAN: "#3F6E75",
          Color.GREEN: "#177500",
          Color.INTENSE_BLACK: "#3F6E75",
          Color.INTENSE_BLUE: "#2300CE",
          Color.INTENSE_CYAN: "#3F6E75",
          Color.INTENSE_GREEN: "#3F6E75",
          Color.INTENSE_PURPLE: "#A90D91",
          Color.INTENSE_RED: "#C41A16",
          Color.INTENSE_WHITE: "#3F6E75",
          Color.INTENSE_YELLOW: "#836C28",
          Color.DEFAULT: "noinherit",
          Color.PURPLE: "#A90D91",
          Color.RED: "#C41A16",
          Color.WHITE: "#3F6E75",
          Color.YELLOW: "#836C28",
      }
      return style
  
  
  STYLES = LazyDict(
      {
          "algol": _algol_style,
          "algol_nu": _algol_nu_style,
          "autumn": _autumn_style,
          "borland": _borland_style,
          "bw": _bw_style,
          "colorful": _colorful_style,
          "default": _default_style,
          "emacs": _emacs_style,
          "friendly": _friendly_style,
          "fruity": _fruity_style,
          "igor": _igor_style,
          "lovelace": _lovelace_style,
          "manni": _manni_style,
          "monokai": _monokai_style,
          "murphy": _murphy_style,
          "native": _native_style,
          "paraiso-dark": _paraiso_dark_style,
          "paraiso-light": _paraiso_light_style,
          "pastie": _pastie_style,
          "perldoc": _perldoc_style,
          "rrt": _rrt_style,
          "tango": _tango_style,
          "trac": _trac_style,
          "vim": _vim_style,
          "vs": _vs_style,
          "xcode": _xcode_style,
      },
      globals(),
      "STYLES",
  )
  
  del (
      _algol_style,
      _algol_nu_style,
      _autumn_style,
      _borland_style,
      _bw_style,
      _colorful_style,
      _default_style,
      _emacs_style,
      _friendly_style,
      _fruity_style,
      _igor_style,
      _lovelace_style,
      _manni_style,
      _monokai_style,
      _murphy_style,
      _native_style,
      _paraiso_dark_style,
      _paraiso_light_style,
      _pastie_style,
      _perldoc_style,
      _rrt_style,
      _tango_style,
      _trac_style,
      _vim_style,
      _vs_style,
      _xcode_style,
  )
  
  
  # dynamic styles
  def make_pygments_style(palette):
      """Makes a pygments style based on a color palette."""
      global Color
      style = {getattr(Color, "DEFAULT"): "noinherit"}
      for name, t in BASE_XONSH_COLORS.items():
          color = find_closest_color(t, palette)
          style[getattr(Color, name)] = "#" + color
      return style
  
  
  def pygments_style_by_name(name):
      """Gets or makes a pygments color style by its name."""
      if name in STYLES:
          return STYLES[name]
      pstyle = get_style_by_name(name)
      palette = make_palette(pstyle.styles.values())
      astyle = make_pygments_style(palette)
      STYLES[name] = astyle
      return astyle
  
  
  def _monkey_patch_pygments_codes():
      """ Monky patch pygments' dict of console codes,
          with new color names
      """
      if pygments_version_info() and pygments_version_info() >= (2, 4, 0):
          return
  
      import pygments.console
  
      if "brightblack" in pygments.console.codes:
          # Assume that colors are already fixed in pygments
          # for example when using pygments from source
          return
  
      if not getattr(pygments.console, "_xonsh_patched", False):
          patched_codes = {}
          for new, old in PTK_NEW_OLD_COLOR_MAP.items():
              if old in pygments.console.codes:
                  patched_codes[new[1:]] = pygments.console.codes[old]
          pygments.console.codes.update(patched_codes)
          pygments.console._xonsh_patched = True
  
  
  #
  # Formatter
  #
  
  
  @lazyobject
  def XonshTerminal256Formatter():
  
      if (
          ptk_version_info()
          and ptk_version_info() > (2, 0)
          and pygments_version_info()
          and (2, 2, 0) <= pygments_version_info() < (2, 4, 0)
      ):
          # Monky patch pygments' dict of console codes
          # with the new color names used by PTK2
          # Can be removed once pygment names get fixed.
          _monkey_patch_pygments_codes()
  
      class XonshTerminal256FormatterProxy(terminal256.Terminal256Formatter):
          """Proxy class for xonsh terminal256 formatting that understands.
          xonsh color tokens.
          """
  
          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              # just keep the opening token for colors.
              color_names = set(map(str, Color.subtypes))
              for name, (opener, closer) in self.style_string.items():
                  if name in color_names:
                      self.style_string[name] = (opener, "")
              # special case DEFAULT, because it is special.
              self.style_string["Token.Color.DEFAULT"] = ("\x1b[39m", "")
  
      return XonshTerminal256FormatterProxy
  
  
  @lazyobject
  def XonshHtmlFormatter():
      from pygments.style import ansicolors
  
      def colorformat(text):
          if text in ansicolors:
              return text
          if text[0:1] == "#":
              col = text[1:]
              if len(col) == 6:
                  return col
              elif len(col) == 3:
                  return col[0] * 2 + col[1] * 2 + col[2] * 2
          elif text == "":
              return ""
          elif text.startswith("var") or text.startswith("calc"):
              return text
          assert False, "wrong color format %r" % text
  
      class XonshHtmlFormatterProxy(html.HtmlFormatter):
          """Proxy class for xonsh HTML formatting that understands.
          xonsh color tokens.
          """
  
          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              # set up classes for colors
              self._ndefs = dict(self.style)
              for t in Color.subtypes:
                  if t not in self.style._styles:
                      self._set_ndef_for_color_token(t)
                  classname = str(t)[5:].replace(".", "").lower()
                  self.ttype2class[t] = classname
                  self.class2style[classname] = self._get_color_token_style(t)
              del self._ndefs
  
          def _get_color_token_style(self, ttype):
              webify = html.webify
              ndef = self._ndefs[ttype]
              style = ""
              if ndef["color"]:
                  style += "color: {}; ".format(webify(ndef["color"]))
              if ndef["bold"]:
                  style += "font-weight: bold; "
              if ndef["italic"]:
                  style += "font-style: italic; "
              if ndef["underline"]:
                  style += "text-decoration: underline; "
              if ndef["bgcolor"]:
                  style += "background-color: {}; ".format(webify(ndef["bgcolor"]))
              if ndef["border"]:
                  style += "border: 1px solid {}; ".format(webify(ndef["border"]))
              return (style[:-2], ttype, len(ttype))
  
          def _set_ndef_for_color_token(self, ttype):
              ndef = self.style._styles.get(ttype.parent, None)
              styledefs = self.style.styles.get(ttype, "").split()
              if not ndef or ttype is None:
                  ndef = ["", 0, 0, 0, "", "", 0, 0, 0]
              elif "noinherit" in styledefs and ttype is not Token:
                  ndef = self.style._styles[Token][:]
              else:
                  ndef = ndef[:]
              self.style._styles[ttype] = ndef
              for styledef in self.style.styles.get(ttype, "").split():
                  if styledef == "noinherit":
                      pass
                  elif styledef == "bold":
                      ndef[1] = 1
                  elif styledef == "nobold":
                      ndef[1] = 0
                  elif styledef == "italic":
                      ndef[2] = 1
                  elif styledef == "noitalic":
                      ndef[2] = 0
                  elif styledef == "underline":
                      ndef[3] = 1
                  elif styledef == "nounderline":
                      ndef[3] = 0
                  elif styledef[:3] == "bg:":
                      ndef[4] = colorformat(styledef[3:])
                  elif styledef[:7] == "border:":
                      ndef[5] = colorformat(styledef[7:])
                  elif styledef == "roman":
                      ndef[6] = 1
                  elif styledef == "sans":
                      ndef[7] = 1
                  elif styledef == "mono":
                      ndef[8] = 1
                  else:
                      ndef[0] = colorformat(styledef)
              self._ndefs[ttype] = self.style.style_for_token(ttype)
  
      return XonshHtmlFormatterProxy
  
  
  color_file_extension_RE = LazyObject(
      lambda: re.compile(r".*(\.\w+)$"), globals(), "color_file_extension_RE"
  )
  
  
  file_color_tokens = dict()  # type:ignore
  """Parallel to LS_COLORS, keyed by dircolors keys, but value is a Color token.
  Initialized by XonshStyle."""
  
  
  # define as external funcition so tests can reference it too.
  def on_lscolors_change(key, oldvalue, newvalue, **kwargs):
      """if LS_COLORS updated, update file_color_tokens and  corresponding color token in style"""
      if newvalue is None:
          del file_color_tokens[key]
      else:
          file_color_tokens[key] = color_token_by_name(newvalue)
  
  
  events.on_lscolors_change(on_lscolors_change)
  
  
  def color_file(file_path: str, path_stat: os.stat_result) -> tp.Tuple[_TokenType, str]:
      """Determine color to use for file *approximately* as ls --color would,
         given lstat() results and its path.
  
      Parameters
      ----------
      file_path:
          relative path of file (as user typed it).
      path_stat:
          lstat() results for file_path.
  
      Returns
      -------
      color token, color_key
  
      Notes
      -----
      * implementation follows one authority:
        https://github.com/coreutils/coreutils/blob/master/src/ls.c#L4879
      * except:
  
        1. does not return 'mi'.  That's the color ls uses to show the (missing) *target* of a symlink
           (in ls -l, not ls).
        2. in dircolors, setting type code to '0 or '00' bypasses that test and proceeds to others.
           In our implementation, setting code to '00' paints the file with no color.
           This is arguably a bug.
      """
  
      lsc = builtins.__xonsh__.env["LS_COLORS"]  # type:ignore
      color_key = "fi"
  
      # if symlink, get info on (final) target
      if stat.S_ISLNK(path_stat.st_mode):
          try:
              tar_path_stat = os.stat(file_path)  # and work with its properties
              if lsc.is_target("ln"):  # if ln=target
                  path_stat = tar_path_stat
          except FileNotFoundError:  # bug always color broken link 'or'
              color_key = "or"  # early exit
              ret_color_token = file_color_tokens.get(color_key, Text)
              return ret_color_token, color_key
  
      mode = path_stat.st_mode
  
      if stat.S_ISREG(mode):
          if mode & stat.S_ISUID:
              color_key = "su"
          elif mode & stat.S_ISGID:
              color_key = "sg"
          else:
              cap = os_listxattr(file_path, follow_symlinks=False)
              if cap and "security.capability" in cap:  # protect None return on some OS?
                  color_key = "ca"
              elif stat.S_IMODE(mode) & (stat.S_IXUSR + stat.S_IXGRP + stat.S_IXOTH):
                  color_key = "ex"
              elif path_stat.st_nlink > 1:
                  color_key = "mh"
              else:
                  color_key = "fi"
      elif stat.S_ISDIR(mode):  # ls --color doesn't colorize sticky or ow if not dirs...
          color_key = "di"
          if not (ON_WINDOWS):  # on Windows, these do not mean what you think they mean.
              if (mode & stat.S_ISVTX) and (mode & stat.S_IWOTH):
                  color_key = "tw"
              elif mode & stat.S_IWOTH:
                  color_key = "ow"
              elif mode & stat.S_ISVTX:
                  color_key = "st"
      elif stat.S_ISLNK(mode):
          color_key = "ln"
      elif stat.S_ISFIFO(mode):
          color_key = "pi"
      elif stat.S_ISSOCK(mode):
          color_key = "so"
      elif stat.S_ISBLK(mode):
          color_key = "bd"
      elif stat.S_ISCHR(mode):
          color_key = "cd"
      elif stat.S_ISDOOR(mode):  # type:ignore
          color_key = "do"
      else:
          color_key = "or"  # any other type --> orphan
  
      # if still normal file -- try color by file extension.
      # note: symlink to *.<ext> will be colored 'fi' unless the symlink itself
      # ends with .<ext>. `ls` does the same.  Bug-for-bug compatibility!
      if color_key == "fi":
          match = color_file_extension_RE.match(file_path)
          if match:
              ext = "*" + match.group(1)  # look for *.<fileExtension> coloring
              if ext in lsc:
                  color_key = ext
  
      ret_color_token = file_color_tokens.get(color_key, Text)
  
      return ret_color_token, color_key
  
  
  # pygments hooks.
  
  
  def _command_is_valid(cmd):
      try:
          cmd_abspath = os.path.abspath(os.path.expanduser(cmd))
      except (FileNotFoundError, OSError):
          return False
      return (cmd in builtins.__xonsh__.commands_cache and not iskeyword(cmd)) or (
          os.path.isfile(cmd_abspath) and os.access(cmd_abspath, os.X_OK)
      )
  
  
  def _command_is_autocd(cmd):
      if not builtins.__xonsh__.env.get("AUTO_CD", False):
          return False
      try:
          cmd_abspath = os.path.abspath(os.path.expanduser(cmd))
      except (FileNotFoundError, OSError):
          return False
      return os.path.isdir(cmd_abspath)
  
  
  def subproc_cmd_callback(_, match):
      """Yield Builtin token if match contains valid command,
      otherwise fallback to fallback lexer.
      """
      cmd = match.group()
      yield match.start(), Name.Builtin if _command_is_valid(cmd) else Error, cmd
  
  
  def subproc_arg_callback(_, match):
      """Check if match contains valid path"""
      text = match.group()
      yieldVal = Text
      try:
          path = os.path.expanduser(text)
          path_stat = os.lstat(path)  # lstat() will raise FNF if not a real file
          yieldVal, _ = color_file(path, path_stat)
      except (FileNotFoundError, OSError):
          pass
  
      yield (match.start(), yieldVal, text)
  
  
  COMMAND_TOKEN_RE = r'[^=\s\[\]{}()$"\'`<&|;!]+(?=\s|$|\)|\]|\}|!)'
  
  
  class XonshLexer(Python3Lexer):
      """Xonsh console lexer for pygments."""
  
      name = "Xonsh lexer"
      aliases = ["xonsh2", "xsh"]
      filenames = ["*.xsh", "*xonshrc"]
  
      def __init__(self, *args, **kwargs):
          # If the lexer is loaded as a pygment plugin, we have to mock
          # __xonsh__.env and __xonsh__.commands_cache
          if not hasattr(builtins, "__xonsh__"):
              from argparse import Namespace
  
              setattr(builtins, "__xonsh__", Namespace())
          if not hasattr(builtins.__xonsh__, "env"):
              setattr(builtins.__xonsh__, "env", {})
              if ON_WINDOWS:
                  pathext = os_environ.get("PATHEXT", [".EXE", ".BAT", ".CMD"])
                  builtins.__xonsh__.env["PATHEXT"] = pathext.split(os.pathsep)
          if not hasattr(builtins.__xonsh__, "commands_cache"):
              setattr(builtins.__xonsh__, "commands_cache", CommandsCache())
          _ = builtins.__xonsh__.commands_cache.all_commands  # NOQA
          super().__init__(*args, **kwargs)
  
      tokens = {
          "mode_switch_brackets": [
              (r"(\$)(\{)", bygroups(Keyword, Punctuation), "py_curly_bracket"),
              (r"(@)(\()", bygroups(Keyword, Punctuation), "py_bracket"),
              (
                  r"([\!\$])(\()",
                  bygroups(Keyword, Punctuation),
                  ("subproc_bracket", "subproc_start"),
              ),
              (
                  r"(@\$)(\()",
                  bygroups(Keyword, Punctuation),
                  ("subproc_bracket", "subproc_start"),
              ),
              (
                  r"([\!\$])(\[)",
                  bygroups(Keyword, Punctuation),
                  ("subproc_square_bracket", "subproc_start"),
              ),
              (r"(g?)(`)", bygroups(String.Affix, String.Backtick), "backtick_re"),
          ],
          "subproc_bracket": [(r"\)", Punctuation, "#pop"), include("subproc")],
          "subproc_square_bracket": [(r"\]", Punctuation, "#pop"), include("subproc")],
          "py_bracket": [(r"\)", Punctuation, "#pop"), include("root")],
          "py_curly_bracket": [(r"\}", Punctuation, "#pop"), include("root")],
          "backtick_re": [
              (r"[\.\^\$\*\+\?\[\]\|]", String.Regex),
              (r"({[0-9]+}|{[0-9]+,[0-9]+})\??", String.Regex),
              (r"\\([0-9]+|[AbBdDsSwWZabfnrtuUvx\\])", String.Escape),
              (r"`", String.Backtick, "#pop"),
              (r"[^`\.\^\$\*\+\?\[\]\|]+", String.Backtick),
          ],
          "root": [
              (r"\?", Keyword),
              (r"(?<=\w)!", Keyword),
              (r"\$\w+", Name.Variable),
              (r"\(", Punctuation, "py_bracket"),
              (r"\{", Punctuation, "py_curly_bracket"),
              include("mode_switch_brackets"),
              inherit,
          ],
          "subproc_start": [
              (r"\s+", Whitespace),
              (COMMAND_TOKEN_RE, subproc_cmd_callback, "#pop"),
              (r"", Whitespace, "#pop"),
          ],
          "subproc": [
              include("mode_switch_brackets"),
              (r"&&|\|\|", Operator, "subproc_start"),
              (r'"(\\\\|\\[0-7]+|\\.|[^"\\])*"', String.Double),
              (r"'(\\\\|\\[0-7]+|\\.|[^'\\])*'", String.Single),
              (r"(?<=\w|\s)!", Keyword, "subproc_macro"),
              (r"^!", Keyword, "subproc_macro"),
              (r";", Punctuation, "subproc_start"),
              (r"&|=", Punctuation),
              (r"\|", Punctuation, "subproc_start"),
              (r"\s+", Text),
              (r'[^=\s\[\]{}()$"\'`<&|;]+', subproc_arg_callback),
              (r"<", Text),
              (r"\$\w+", Name.Variable),
          ],
          "subproc_macro": [
              (r"(\s*)([^\n]+)", bygroups(Whitespace, String)),
              (r"", Whitespace, "#pop"),
          ],
      }
  
      def get_tokens_unprocessed(self, text):
          """Check first command, then call super.get_tokens_unprocessed
          with root or subproc state"""
          start = 0
          state = ("root",)
          m = re.match(r"(\s*)({})".format(COMMAND_TOKEN_RE), text)
          if m is not None:
              yield m.start(1), Whitespace, m.group(1)
              start = m.end(1)
              cmd = m.group(2)
              cmd_is_valid = _command_is_valid(cmd)
              cmd_is_autocd = _command_is_autocd(cmd)
  
              if cmd_is_valid or cmd_is_autocd:
                  yield (m.start(2), Name.Builtin if cmd_is_valid else Name.Constant, cmd)
                  start = m.end(2)
                  state = ("subproc",)
  
          for i, t, v in super().get_tokens_unprocessed(text[start:], state):
              yield i + start, t, v
  
  
  class XonshConsoleLexer(XonshLexer):
      """Xonsh console lexer for pygments."""
  
      name = "Xonsh console lexer"
      aliases = ["xonshcon"]
      filenames: tp.List[str] = []
  
      tokens = {
          "root": [
              (r"^(>>>|\.\.\.) ", Generic.Prompt),
              (r"\n(>>>|\.\.\.)", Generic.Prompt),
              (r"\n(?![>.][>.][>.] )([^\n]*)", Generic.Output),
              (r"\n(?![>.][>.][>.] )(.*?)$", Generic.Output),
              inherit,
          ]
      }
  