1"""Xonsh color styling tools that simulate pygments, when it is unavailable.""" 2import builtins 3import string 4from collections import defaultdict 5 6from xonsh.platform import HAS_PYGMENTS 7from xonsh.lazyasd import LazyObject 8from xonsh.color_tools import RE_BACKGROUND 9 10 11class _TokenType(tuple): 12 """ 13 Forked from the pygments project 14 https://bitbucket.org/birkenfeld/pygments-main 15 Copyright (c) 2006-2017 by the respective authors, All rights reserved. 16 See https://bitbucket.org/birkenfeld/pygments-main/raw/05818a4ef9891d9ac22c851f7b3ea4b4fce460ab/AUTHORS 17 """ 18 19 parent = None 20 21 def split(self): 22 buf = [] 23 node = self 24 while node is not None: 25 buf.append(node) 26 node = node.parent 27 buf.reverse() 28 return buf 29 30 def __init__(self, *args): 31 # no need to call super.__init__ 32 self.subtypes = set() 33 34 def __contains__(self, val): 35 return self is val or (type(val) is self.__class__ and val[: len(self)] == self) 36 37 def __getattr__(self, val): 38 if not val or not val[0].isupper(): 39 return tuple.__getattribute__(self, val) 40 new = _TokenType(self + (val,)) 41 setattr(self, val, new) 42 self.subtypes.add(new) 43 new.parent = self 44 return new 45 46 def __repr__(self): 47 return "Token" + (self and "." or "") + ".".join(self) 48 49 def __copy__(self): 50 # These instances are supposed to be singletons 51 return self 52 53 def __deepcopy__(self, memo): 54 # These instances are supposed to be singletons 55 return self 56 57 58Token = _TokenType() 59Color = Token.Color 60 61 62def partial_color_tokenize(template): 63 """Tokenizes a template string containing colors. Will return a list 64 of tuples mapping the token to the string which has that color. 65 These sub-strings maybe templates themselves. 66 """ 67 if HAS_PYGMENTS and hasattr(builtins, "__xonsh_shell__"): 68 styles = __xonsh_shell__.shell.styler.styles 69 elif hasattr(builtins, "__xonsh_shell__"): 70 styles = DEFAULT_STYLE_DICT 71 else: 72 styles = None 73 color = Color.NO_COLOR 74 try: 75 toks, color = _partial_color_tokenize_main(template, styles) 76 except Exception: 77 toks = [(Color.NO_COLOR, template)] 78 if styles is not None: 79 styles[color] # ensure color is available 80 return toks 81 82 83def _partial_color_tokenize_main(template, styles): 84 formatter = string.Formatter() 85 bopen = "{" 86 bclose = "}" 87 colon = ":" 88 expl = "!" 89 color = Color.NO_COLOR 90 fg = bg = None 91 value = "" 92 toks = [] 93 for literal, field, spec, conv in formatter.parse(template): 94 if field is None: 95 value += literal 96 elif field in KNOWN_COLORS or "#" in field: 97 value += literal 98 next_color, fg, bg = color_by_name(field, fg, bg) 99 if next_color is not color: 100 if len(value) > 0: 101 toks.append((color, value)) 102 if styles is not None: 103 styles[color] # ensure color is available 104 color = next_color 105 value = "" 106 elif field is not None: 107 parts = [literal, bopen, field] 108 if conv is not None and len(conv) > 0: 109 parts.append(expl) 110 parts.append(conv) 111 if spec is not None and len(spec) > 0: 112 parts.append(colon) 113 parts.append(spec) 114 parts.append(bclose) 115 value += "".join(parts) 116 else: 117 value += literal 118 toks.append((color, value)) 119 return toks, color 120 121 122def color_by_name(name, fg=None, bg=None): 123 """Converts a color name to a color token, foreground name, 124 and background name. Will take into consideration current foreground 125 and background colors, if provided. 126 127 Parameters 128 ---------- 129 name : str 130 Color name. 131 fg : str, optional 132 Foreground color name. 133 bg : str, optional 134 Background color name. 135 136 Returns 137 ------- 138 tok : Token 139 Pygments Token.Color subclass 140 fg : str or None 141 New computed foreground color name. 142 bg : str or None 143 New computed background color name. 144 """ 145 name = name.upper() 146 if name == "NO_COLOR": 147 return Color.NO_COLOR, None, None 148 m = RE_BACKGROUND.search(name) 149 if m is None: # must be foreground color 150 fg = norm_name(name) 151 else: 152 bg = norm_name(name) 153 # assemble token 154 if fg is None and bg is None: 155 tokname = "NO_COLOR" 156 elif fg is None: 157 tokname = bg 158 elif bg is None: 159 tokname = fg 160 else: 161 tokname = fg + "__" + bg 162 tok = getattr(Color, tokname) 163 return tok, fg, bg 164 165 166def norm_name(name): 167 """Normalizes a color name.""" 168 return name.replace("#", "HEX").replace("BGHEX", "BACKGROUND_HEX") 169 170 171KNOWN_COLORS = LazyObject( 172 lambda: frozenset( 173 [ 174 "BACKGROUND_BLACK", 175 "BACKGROUND_BLUE", 176 "BACKGROUND_CYAN", 177 "BACKGROUND_GREEN", 178 "BACKGROUND_INTENSE_BLACK", 179 "BACKGROUND_INTENSE_BLUE", 180 "BACKGROUND_INTENSE_CYAN", 181 "BACKGROUND_INTENSE_GREEN", 182 "BACKGROUND_INTENSE_PURPLE", 183 "BACKGROUND_INTENSE_RED", 184 "BACKGROUND_INTENSE_WHITE", 185 "BACKGROUND_INTENSE_YELLOW", 186 "BACKGROUND_PURPLE", 187 "BACKGROUND_RED", 188 "BACKGROUND_WHITE", 189 "BACKGROUND_YELLOW", 190 "BLACK", 191 "BLUE", 192 "BOLD_BLACK", 193 "BOLD_BLUE", 194 "BOLD_CYAN", 195 "BOLD_GREEN", 196 "BOLD_INTENSE_BLACK", 197 "BOLD_INTENSE_BLUE", 198 "BOLD_INTENSE_CYAN", 199 "BOLD_INTENSE_GREEN", 200 "BOLD_INTENSE_PURPLE", 201 "BOLD_INTENSE_RED", 202 "BOLD_INTENSE_WHITE", 203 "BOLD_INTENSE_YELLOW", 204 "BOLD_PURPLE", 205 "BOLD_RED", 206 "BOLD_UNDERLINE_BLACK", 207 "BOLD_UNDERLINE_BLUE", 208 "BOLD_UNDERLINE_CYAN", 209 "BOLD_UNDERLINE_GREEN", 210 "BOLD_UNDERLINE_INTENSE_BLACK", 211 "BOLD_UNDERLINE_INTENSE_BLUE", 212 "BOLD_UNDERLINE_INTENSE_CYAN", 213 "BOLD_UNDERLINE_INTENSE_GREEN", 214 "BOLD_UNDERLINE_INTENSE_PURPLE", 215 "BOLD_UNDERLINE_INTENSE_RED", 216 "BOLD_UNDERLINE_INTENSE_WHITE", 217 "BOLD_UNDERLINE_INTENSE_YELLOW", 218 "BOLD_UNDERLINE_PURPLE", 219 "BOLD_UNDERLINE_RED", 220 "BOLD_UNDERLINE_WHITE", 221 "BOLD_UNDERLINE_YELLOW", 222 "BOLD_WHITE", 223 "BOLD_YELLOW", 224 "CYAN", 225 "GREEN", 226 "INTENSE_BLACK", 227 "INTENSE_BLUE", 228 "INTENSE_CYAN", 229 "INTENSE_GREEN", 230 "INTENSE_PURPLE", 231 "INTENSE_RED", 232 "INTENSE_WHITE", 233 "INTENSE_YELLOW", 234 "NO_COLOR", 235 "PURPLE", 236 "RED", 237 "UNDERLINE_BLACK", 238 "UNDERLINE_BLUE", 239 "UNDERLINE_CYAN", 240 "UNDERLINE_GREEN", 241 "UNDERLINE_INTENSE_BLACK", 242 "UNDERLINE_INTENSE_BLUE", 243 "UNDERLINE_INTENSE_CYAN", 244 "UNDERLINE_INTENSE_GREEN", 245 "UNDERLINE_INTENSE_PURPLE", 246 "UNDERLINE_INTENSE_RED", 247 "UNDERLINE_INTENSE_WHITE", 248 "UNDERLINE_INTENSE_YELLOW", 249 "UNDERLINE_PURPLE", 250 "UNDERLINE_RED", 251 "UNDERLINE_WHITE", 252 "UNDERLINE_YELLOW", 253 "WHITE", 254 "YELLOW", 255 ] 256 ), 257 globals(), 258 "KNOWN_COLORS", 259) 260 261DEFAULT_STYLE_DICT = LazyObject( 262 lambda: defaultdict( 263 lambda: "", 264 { 265 Token: "", 266 Token.Aborted: "ansibrightblack", 267 Token.AutoSuggestion: "ansibrightblack", 268 Token.Color.BACKGROUND_BLACK: "bg:ansiblack", 269 Token.Color.BACKGROUND_BLUE: "bg:ansiblue", 270 Token.Color.BACKGROUND_CYAN: "bg:ansicyan", 271 Token.Color.BACKGROUND_GREEN: "bg:ansigreen", 272 Token.Color.BACKGROUND_INTENSE_BLACK: "bg:ansibrightblack", 273 Token.Color.BACKGROUND_INTENSE_BLUE: "bg:ansibrightblue", 274 Token.Color.BACKGROUND_INTENSE_CYAN: "bg:ansibrightcyan", 275 Token.Color.BACKGROUND_INTENSE_GREEN: "bg:ansibrightgreen", 276 Token.Color.BACKGROUND_INTENSE_PURPLE: "bg:ansibrightmagenta", 277 Token.Color.BACKGROUND_INTENSE_RED: "bg:ansibrightred", 278 Token.Color.BACKGROUND_INTENSE_WHITE: "bg:ansiwhite", 279 Token.Color.BACKGROUND_INTENSE_YELLOW: "bg:ansibrightyellow", 280 Token.Color.BACKGROUND_PURPLE: "bg:ansimagenta", 281 Token.Color.BACKGROUND_RED: "bg:ansired", 282 Token.Color.BACKGROUND_WHITE: "bg:ansigray", 283 Token.Color.BACKGROUND_YELLOW: "bg:ansiyellow", 284 Token.Color.BLACK: "ansiblack", 285 Token.Color.BLUE: "ansiblue", 286 Token.Color.BOLD_BLACK: "bold ansiblack", 287 Token.Color.BOLD_BLUE: "bold ansiblue", 288 Token.Color.BOLD_CYAN: "bold ansicyan", 289 Token.Color.BOLD_GREEN: "bold ansigreen", 290 Token.Color.BOLD_INTENSE_BLACK: "bold ansibrightblack", 291 Token.Color.BOLD_INTENSE_BLUE: "bold ansibrightblue", 292 Token.Color.BOLD_INTENSE_CYAN: "bold ansibrightcyan", 293 Token.Color.BOLD_INTENSE_GREEN: "bold ansibrightgreen", 294 Token.Color.BOLD_INTENSE_PURPLE: "bold ansibrightmagenta", 295 Token.Color.BOLD_INTENSE_RED: "bold ansibrightred", 296 Token.Color.BOLD_INTENSE_WHITE: "bold ansiwhite", 297 Token.Color.BOLD_INTENSE_YELLOW: "bold ansibrightyellow", 298 Token.Color.BOLD_PURPLE: "bold ansimagenta", 299 Token.Color.BOLD_RED: "bold ansired", 300 Token.Color.BOLD_UNDERLINE_BLACK: "bold underline ansiblack", 301 Token.Color.BOLD_UNDERLINE_BLUE: "bold underline ansiblue", 302 Token.Color.BOLD_UNDERLINE_CYAN: "bold underline ansicyan", 303 Token.Color.BOLD_UNDERLINE_GREEN: "bold underline ansigreen", 304 Token.Color.BOLD_UNDERLINE_INTENSE_BLACK: "bold underline ansibrightblack", 305 Token.Color.BOLD_UNDERLINE_INTENSE_BLUE: "bold underline ansibrightblue", 306 Token.Color.BOLD_UNDERLINE_INTENSE_CYAN: "bold underline ansibrightcyan", 307 Token.Color.BOLD_UNDERLINE_INTENSE_GREEN: "bold underline ansibrightgreen", 308 Token.Color.BOLD_UNDERLINE_INTENSE_PURPLE: "bold underline ansibrightmagenta", 309 Token.Color.BOLD_UNDERLINE_INTENSE_RED: "bold underline ansibrightred", 310 Token.Color.BOLD_UNDERLINE_INTENSE_WHITE: "bold underline ansiwhite", 311 Token.Color.BOLD_UNDERLINE_INTENSE_YELLOW: "bold underline ansibrightyellow", 312 Token.Color.BOLD_UNDERLINE_PURPLE: "bold underline ansimagenta", 313 Token.Color.BOLD_UNDERLINE_RED: "bold underline ansired", 314 Token.Color.BOLD_UNDERLINE_WHITE: "bold underline ansigray", 315 Token.Color.BOLD_UNDERLINE_YELLOW: "bold underline ansiyellow", 316 Token.Color.BOLD_WHITE: "bold ansigray", 317 Token.Color.BOLD_YELLOW: "bold ansiyellow", 318 Token.Color.CYAN: "ansicyan", 319 Token.Color.GREEN: "ansigreen", 320 Token.Color.INTENSE_BLACK: "ansibrightblack", 321 Token.Color.INTENSE_BLUE: "ansibrightblue", 322 Token.Color.INTENSE_CYAN: "ansibrightcyan", 323 Token.Color.INTENSE_GREEN: "ansibrightgreen", 324 Token.Color.INTENSE_PURPLE: "ansibrightmagenta", 325 Token.Color.INTENSE_RED: "ansibrightred", 326 Token.Color.INTENSE_WHITE: "ansiwhite", 327 Token.Color.INTENSE_YELLOW: "ansibrightyellow", 328 Token.Color.NO_COLOR: "noinherit", 329 Token.Color.PURPLE: "ansimagenta", 330 Token.Color.RED: "ansired", 331 Token.Color.UNDERLINE_BLACK: "underline ansiblack", 332 Token.Color.UNDERLINE_BLUE: "underline ansiblue", 333 Token.Color.UNDERLINE_CYAN: "underline ansicyan", 334 Token.Color.UNDERLINE_GREEN: "underline ansigreen", 335 Token.Color.UNDERLINE_INTENSE_BLACK: "underline ansibrightblack", 336 Token.Color.UNDERLINE_INTENSE_BLUE: "underline ansibrightblue", 337 Token.Color.UNDERLINE_INTENSE_CYAN: "underline ansibrightcyan", 338 Token.Color.UNDERLINE_INTENSE_GREEN: "underline ansibrightgreen", 339 Token.Color.UNDERLINE_INTENSE_PURPLE: "underline ansibrightmagenta", 340 Token.Color.UNDERLINE_INTENSE_RED: "underline ansibrightred", 341 Token.Color.UNDERLINE_INTENSE_WHITE: "underline ansiwhite", 342 Token.Color.UNDERLINE_INTENSE_YELLOW: "underline ansibrightyellow", 343 Token.Color.UNDERLINE_PURPLE: "underline ansimagenta", 344 Token.Color.UNDERLINE_RED: "underline ansired", 345 Token.Color.UNDERLINE_WHITE: "underline ansigray", 346 Token.Color.UNDERLINE_YELLOW: "underline ansiyellow", 347 Token.Color.WHITE: "ansigray", 348 Token.Color.YELLOW: "ansiyellow", 349 Token.Comment: "underline ansicyan", 350 Token.Comment.Hashbang: "", 351 Token.Comment.Multiline: "", 352 Token.Comment.Preproc: "underline ansiyellow", 353 Token.Comment.PreprocFile: "", 354 Token.Comment.Single: "", 355 Token.Comment.Special: "", 356 Token.Error: "ansibrightred", 357 Token.Escape: "", 358 Token.Generic: "", 359 Token.Generic.Deleted: "ansired", 360 Token.Generic.Emph: "underline", 361 Token.Generic.Error: "bold ansibrightred", 362 Token.Generic.Heading: "bold ansiblue", 363 Token.Generic.Inserted: "ansibrightgreen", 364 Token.Generic.Output: "ansiblue", 365 Token.Generic.Prompt: "bold ansiblue", 366 Token.Generic.Strong: "", 367 Token.Generic.Subheading: "bold ansimagenta", 368 Token.Generic.Traceback: "ansiblue", 369 Token.Keyword: "bold ansigreen", 370 Token.Keyword.Constant: "", 371 Token.Keyword.Declaration: "", 372 Token.Keyword.Namespace: "", 373 Token.Keyword.Pseudo: "nobold", 374 Token.Keyword.Reserved: "", 375 Token.Keyword.Type: "nobold ansired", 376 Token.Literal: "", 377 Token.Literal.Date: "", 378 Token.Literal.Number: "ansibrightblack", 379 Token.Literal.Number.Bin: "", 380 Token.Literal.Number.Float: "", 381 Token.Literal.Number.Hex: "", 382 Token.Literal.Number.Integer: "", 383 Token.Literal.Number.Integer.Long: "", 384 Token.Literal.Number.Oct: "", 385 Token.Literal.String: "ansibrightred", 386 Token.Literal.String.Affix: "", 387 Token.Literal.String.Backtick: "", 388 Token.Literal.String.Char: "", 389 Token.Literal.String.Delimiter: "", 390 Token.Literal.String.Doc: "underline", 391 Token.Literal.String.Double: "", 392 Token.Literal.String.Escape: "bold ansiyellow", 393 Token.Literal.String.Heredoc: "", 394 Token.Literal.String.Interpol: "bold ansimagenta", 395 Token.Literal.String.Other: "ansigreen", 396 Token.Literal.String.Regex: "ansimagenta", 397 Token.Literal.String.Single: "", 398 Token.Literal.String.Symbol: "ansiyellow", 399 Token.Menu.Completions: "bg:ansigray ansiblack", 400 Token.Menu.Completions.Completion: "", 401 Token.Menu.Completions.Completion.Current: "bg:ansibrightblack ansiwhite", 402 Token.Name: "", 403 Token.Name.Attribute: "ansibrightyellow", 404 Token.Name.Builtin: "ansigreen", 405 Token.Name.Builtin.Pseudo: "", 406 Token.Name.Class: "bold ansibrightblue", 407 Token.Name.Constant: "ansired", 408 Token.Name.Decorator: "ansibrightmagenta", 409 Token.Name.Entity: "bold ansigray", 410 Token.Name.Exception: "bold ansibrightred", 411 Token.Name.Function: "ansibrightblue", 412 Token.Name.Function.Magic: "", 413 Token.Name.Label: "ansibrightyellow", 414 Token.Name.Namespace: "bold ansibrightblue", 415 Token.Name.Other: "", 416 Token.Name.Property: "", 417 Token.Name.Tag: "bold ansigreen", 418 Token.Name.Variable: "ansiblue", 419 Token.Name.Variable.Class: "", 420 Token.Name.Variable.Global: "", 421 Token.Name.Variable.Instance: "", 422 Token.Name.Variable.Magic: "", 423 Token.Operator: "ansibrightblack", 424 Token.Operator.Word: "bold ansimagenta", 425 Token.Other: "", 426 Token.Punctuation: "", 427 Token.Scrollbar: "bg:ansibrightblack", 428 Token.Scrollbar.Arrow: "bg:ansiblack ansiwhite bold", 429 Token.Scrollbar.Button: "bg:ansiblack", 430 Token.Text: "", 431 Token.Text.Whitespace: "ansigray", 432 }, 433 ), 434 globals(), 435 "DEFAULT_STYLE_DICT", 436) 437