PageRenderTime 5670ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/monitor_batch/pymodules/python2.7/lib/python/ipython-2.2.0-py2.7.egg/IPython/qt/console/ansi_code_processor.py

https://gitlab.com/pooja043/Globus_Docker_4
Python | 378 lines | 237 code | 48 blank | 93 comment | 87 complexity | d941b21bf8c378295dd8201a9a146fcc MD5 | raw file
  1. """ Utilities for processing ANSI escape codes and special ASCII characters.
  2. """
  3. #-----------------------------------------------------------------------------
  4. # Imports
  5. #-----------------------------------------------------------------------------
  6. # Standard library imports
  7. from collections import namedtuple
  8. import re
  9. # System library imports
  10. from IPython.external.qt import QtGui
  11. # Local imports
  12. from IPython.utils.py3compat import string_types
  13. #-----------------------------------------------------------------------------
  14. # Constants and datatypes
  15. #-----------------------------------------------------------------------------
  16. # An action for erase requests (ED and EL commands).
  17. EraseAction = namedtuple('EraseAction', ['action', 'area', 'erase_to'])
  18. # An action for cursor move requests (CUU, CUD, CUF, CUB, CNL, CPL, CHA, CUP,
  19. # and HVP commands).
  20. # FIXME: Not implemented in AnsiCodeProcessor.
  21. MoveAction = namedtuple('MoveAction', ['action', 'dir', 'unit', 'count'])
  22. # An action for scroll requests (SU and ST) and form feeds.
  23. ScrollAction = namedtuple('ScrollAction', ['action', 'dir', 'unit', 'count'])
  24. # An action for the carriage return character
  25. CarriageReturnAction = namedtuple('CarriageReturnAction', ['action'])
  26. # An action for the \n character
  27. NewLineAction = namedtuple('NewLineAction', ['action'])
  28. # An action for the beep character
  29. BeepAction = namedtuple('BeepAction', ['action'])
  30. # An action for backspace
  31. BackSpaceAction = namedtuple('BackSpaceAction', ['action'])
  32. # Regular expressions.
  33. CSI_COMMANDS = 'ABCDEFGHJKSTfmnsu'
  34. CSI_SUBPATTERN = '\[(.*?)([%s])' % CSI_COMMANDS
  35. OSC_SUBPATTERN = '\](.*?)[\x07\x1b]'
  36. ANSI_PATTERN = ('\x01?\x1b(%s|%s)\x02?' % \
  37. (CSI_SUBPATTERN, OSC_SUBPATTERN))
  38. ANSI_OR_SPECIAL_PATTERN = re.compile('(\a|\b|\r(?!\n)|\r?\n)|(?:%s)' % ANSI_PATTERN)
  39. SPECIAL_PATTERN = re.compile('([\f])')
  40. #-----------------------------------------------------------------------------
  41. # Classes
  42. #-----------------------------------------------------------------------------
  43. class AnsiCodeProcessor(object):
  44. """ Translates special ASCII characters and ANSI escape codes into readable
  45. attributes. It also supports a few non-standard, xterm-specific codes.
  46. """
  47. # Whether to increase intensity or set boldness for SGR code 1.
  48. # (Different terminals handle this in different ways.)
  49. bold_text_enabled = False
  50. # We provide an empty default color map because subclasses will likely want
  51. # to use a custom color format.
  52. default_color_map = {}
  53. #---------------------------------------------------------------------------
  54. # AnsiCodeProcessor interface
  55. #---------------------------------------------------------------------------
  56. def __init__(self):
  57. self.actions = []
  58. self.color_map = self.default_color_map.copy()
  59. self.reset_sgr()
  60. def reset_sgr(self):
  61. """ Reset graphics attributs to their default values.
  62. """
  63. self.intensity = 0
  64. self.italic = False
  65. self.bold = False
  66. self.underline = False
  67. self.foreground_color = None
  68. self.background_color = None
  69. def split_string(self, string):
  70. """ Yields substrings for which the same escape code applies.
  71. """
  72. self.actions = []
  73. start = 0
  74. # strings ending with \r are assumed to be ending in \r\n since
  75. # \n is appended to output strings automatically. Accounting
  76. # for that, here.
  77. last_char = '\n' if len(string) > 0 and string[-1] == '\n' else None
  78. string = string[:-1] if last_char is not None else string
  79. for match in ANSI_OR_SPECIAL_PATTERN.finditer(string):
  80. raw = string[start:match.start()]
  81. substring = SPECIAL_PATTERN.sub(self._replace_special, raw)
  82. if substring or self.actions:
  83. yield substring
  84. self.actions = []
  85. start = match.end()
  86. groups = [g for g in match.groups() if (g is not None)]
  87. g0 = groups[0]
  88. if g0 == '\a':
  89. self.actions.append(BeepAction('beep'))
  90. yield None
  91. self.actions = []
  92. elif g0 == '\r':
  93. self.actions.append(CarriageReturnAction('carriage-return'))
  94. yield None
  95. self.actions = []
  96. elif g0 == '\b':
  97. self.actions.append(BackSpaceAction('backspace'))
  98. yield None
  99. self.actions = []
  100. elif g0 == '\n' or g0 == '\r\n':
  101. self.actions.append(NewLineAction('newline'))
  102. yield g0
  103. self.actions = []
  104. else:
  105. params = [ param for param in groups[1].split(';') if param ]
  106. if g0.startswith('['):
  107. # Case 1: CSI code.
  108. try:
  109. params = list(map(int, params))
  110. except ValueError:
  111. # Silently discard badly formed codes.
  112. pass
  113. else:
  114. self.set_csi_code(groups[2], params)
  115. elif g0.startswith(']'):
  116. # Case 2: OSC code.
  117. self.set_osc_code(params)
  118. raw = string[start:]
  119. substring = SPECIAL_PATTERN.sub(self._replace_special, raw)
  120. if substring or self.actions:
  121. yield substring
  122. if last_char is not None:
  123. self.actions.append(NewLineAction('newline'))
  124. yield last_char
  125. def set_csi_code(self, command, params=[]):
  126. """ Set attributes based on CSI (Control Sequence Introducer) code.
  127. Parameters
  128. ----------
  129. command : str
  130. The code identifier, i.e. the final character in the sequence.
  131. params : sequence of integers, optional
  132. The parameter codes for the command.
  133. """
  134. if command == 'm': # SGR - Select Graphic Rendition
  135. if params:
  136. self.set_sgr_code(params)
  137. else:
  138. self.set_sgr_code([0])
  139. elif (command == 'J' or # ED - Erase Data
  140. command == 'K'): # EL - Erase in Line
  141. code = params[0] if params else 0
  142. if 0 <= code <= 2:
  143. area = 'screen' if command == 'J' else 'line'
  144. if code == 0:
  145. erase_to = 'end'
  146. elif code == 1:
  147. erase_to = 'start'
  148. elif code == 2:
  149. erase_to = 'all'
  150. self.actions.append(EraseAction('erase', area, erase_to))
  151. elif (command == 'S' or # SU - Scroll Up
  152. command == 'T'): # SD - Scroll Down
  153. dir = 'up' if command == 'S' else 'down'
  154. count = params[0] if params else 1
  155. self.actions.append(ScrollAction('scroll', dir, 'line', count))
  156. def set_osc_code(self, params):
  157. """ Set attributes based on OSC (Operating System Command) parameters.
  158. Parameters
  159. ----------
  160. params : sequence of str
  161. The parameters for the command.
  162. """
  163. try:
  164. command = int(params.pop(0))
  165. except (IndexError, ValueError):
  166. return
  167. if command == 4:
  168. # xterm-specific: set color number to color spec.
  169. try:
  170. color = int(params.pop(0))
  171. spec = params.pop(0)
  172. self.color_map[color] = self._parse_xterm_color_spec(spec)
  173. except (IndexError, ValueError):
  174. pass
  175. def set_sgr_code(self, params):
  176. """ Set attributes based on SGR (Select Graphic Rendition) codes.
  177. Parameters
  178. ----------
  179. params : sequence of ints
  180. A list of SGR codes for one or more SGR commands. Usually this
  181. sequence will have one element per command, although certain
  182. xterm-specific commands requires multiple elements.
  183. """
  184. # Always consume the first parameter.
  185. if not params:
  186. return
  187. code = params.pop(0)
  188. if code == 0:
  189. self.reset_sgr()
  190. elif code == 1:
  191. if self.bold_text_enabled:
  192. self.bold = True
  193. else:
  194. self.intensity = 1
  195. elif code == 2:
  196. self.intensity = 0
  197. elif code == 3:
  198. self.italic = True
  199. elif code == 4:
  200. self.underline = True
  201. elif code == 22:
  202. self.intensity = 0
  203. self.bold = False
  204. elif code == 23:
  205. self.italic = False
  206. elif code == 24:
  207. self.underline = False
  208. elif code >= 30 and code <= 37:
  209. self.foreground_color = code - 30
  210. elif code == 38 and params and params.pop(0) == 5:
  211. # xterm-specific: 256 color support.
  212. if params:
  213. self.foreground_color = params.pop(0)
  214. elif code == 39:
  215. self.foreground_color = None
  216. elif code >= 40 and code <= 47:
  217. self.background_color = code - 40
  218. elif code == 48 and params and params.pop(0) == 5:
  219. # xterm-specific: 256 color support.
  220. if params:
  221. self.background_color = params.pop(0)
  222. elif code == 49:
  223. self.background_color = None
  224. # Recurse with unconsumed parameters.
  225. self.set_sgr_code(params)
  226. #---------------------------------------------------------------------------
  227. # Protected interface
  228. #---------------------------------------------------------------------------
  229. def _parse_xterm_color_spec(self, spec):
  230. if spec.startswith('rgb:'):
  231. return tuple(map(lambda x: int(x, 16), spec[4:].split('/')))
  232. elif spec.startswith('rgbi:'):
  233. return tuple(map(lambda x: int(float(x) * 255),
  234. spec[5:].split('/')))
  235. elif spec == '?':
  236. raise ValueError('Unsupported xterm color spec')
  237. return spec
  238. def _replace_special(self, match):
  239. special = match.group(1)
  240. if special == '\f':
  241. self.actions.append(ScrollAction('scroll', 'down', 'page', 1))
  242. return ''
  243. class QtAnsiCodeProcessor(AnsiCodeProcessor):
  244. """ Translates ANSI escape codes into QTextCharFormats.
  245. """
  246. # A map from ANSI color codes to SVG color names or RGB(A) tuples.
  247. darkbg_color_map = {
  248. 0 : 'black', # black
  249. 1 : 'darkred', # red
  250. 2 : 'darkgreen', # green
  251. 3 : 'brown', # yellow
  252. 4 : 'darkblue', # blue
  253. 5 : 'darkviolet', # magenta
  254. 6 : 'steelblue', # cyan
  255. 7 : 'grey', # white
  256. 8 : 'grey', # black (bright)
  257. 9 : 'red', # red (bright)
  258. 10 : 'lime', # green (bright)
  259. 11 : 'yellow', # yellow (bright)
  260. 12 : 'deepskyblue', # blue (bright)
  261. 13 : 'magenta', # magenta (bright)
  262. 14 : 'cyan', # cyan (bright)
  263. 15 : 'white' } # white (bright)
  264. # Set the default color map for super class.
  265. default_color_map = darkbg_color_map.copy()
  266. def get_color(self, color, intensity=0):
  267. """ Returns a QColor for a given color code, or None if one cannot be
  268. constructed.
  269. """
  270. if color is None:
  271. return None
  272. # Adjust for intensity, if possible.
  273. if color < 8 and intensity > 0:
  274. color += 8
  275. constructor = self.color_map.get(color, None)
  276. if isinstance(constructor, string_types):
  277. # If this is an X11 color name, we just hope there is a close SVG
  278. # color name. We could use QColor's static method
  279. # 'setAllowX11ColorNames()', but this is global and only available
  280. # on X11. It seems cleaner to aim for uniformity of behavior.
  281. return QtGui.QColor(constructor)
  282. elif isinstance(constructor, (tuple, list)):
  283. return QtGui.QColor(*constructor)
  284. return None
  285. def get_format(self):
  286. """ Returns a QTextCharFormat that encodes the current style attributes.
  287. """
  288. format = QtGui.QTextCharFormat()
  289. # Set foreground color
  290. qcolor = self.get_color(self.foreground_color, self.intensity)
  291. if qcolor is not None:
  292. format.setForeground(qcolor)
  293. # Set background color
  294. qcolor = self.get_color(self.background_color, self.intensity)
  295. if qcolor is not None:
  296. format.setBackground(qcolor)
  297. # Set font weight/style options
  298. if self.bold:
  299. format.setFontWeight(QtGui.QFont.Bold)
  300. else:
  301. format.setFontWeight(QtGui.QFont.Normal)
  302. format.setFontItalic(self.italic)
  303. format.setFontUnderline(self.underline)
  304. return format
  305. def set_background_color(self, color):
  306. """ Given a background color (a QColor), attempt to set a color map
  307. that will be aesthetically pleasing.
  308. """
  309. # Set a new default color map.
  310. self.default_color_map = self.darkbg_color_map.copy()
  311. if color.value() >= 127:
  312. # Colors appropriate for a terminal with a light background. For
  313. # now, only use non-bright colors...
  314. for i in range(8):
  315. self.default_color_map[i + 8] = self.default_color_map[i]
  316. # ...and replace white with black.
  317. self.default_color_map[7] = self.default_color_map[15] = 'black'
  318. # Update the current color map with the new defaults.
  319. self.color_map.update(self.default_color_map)