irc.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. # -*- coding: utf-8 -*-
  2. """
  3. pygments.formatters.irc
  4. ~~~~~~~~~~~~~~~~~~~~~~~
  5. Formatter for IRC output
  6. :copyright: Copyright 2006-2019 by the Pygments team, see AUTHORS.
  7. :license: BSD, see LICENSE for details.
  8. """
  9. import sys
  10. from pygments.formatter import Formatter
  11. from pygments.token import Keyword, Name, Comment, String, Error, \
  12. Number, Operator, Generic, Token, Whitespace
  13. from pygments.util import get_choice_opt
  14. __all__ = ['IRCFormatter']
  15. #: Map token types to a tuple of color values for light and dark
  16. #: backgrounds.
  17. IRC_COLORS = {
  18. Token: ('', ''),
  19. Whitespace: ('gray', 'brightblack'),
  20. Comment: ('gray', 'brightblack'),
  21. Comment.Preproc: ('cyan', 'brightcyan'),
  22. Keyword: ('blue', 'brightblue'),
  23. Keyword.Type: ('cyan', 'brightcyan'),
  24. Operator.Word: ('magenta', 'brightcyan'),
  25. Name.Builtin: ('cyan', 'brightcyan'),
  26. Name.Function: ('green', 'brightgreen'),
  27. Name.Namespace: ('_cyan_', '_brightcyan_'),
  28. Name.Class: ('_green_', '_brightgreen_'),
  29. Name.Exception: ('cyan', 'brightcyan'),
  30. Name.Decorator: ('brightblack', 'gray'),
  31. Name.Variable: ('red', 'brightred'),
  32. Name.Constant: ('red', 'brightred'),
  33. Name.Attribute: ('cyan', 'brightcyan'),
  34. Name.Tag: ('brightblue', 'brightblue'),
  35. String: ('yellow', 'yellow'),
  36. Number: ('blue', 'brightblue'),
  37. Generic.Deleted: ('brightred', 'brightred'),
  38. Generic.Inserted: ('green', 'brightgreen'),
  39. Generic.Heading: ('**', '**'),
  40. Generic.Subheading: ('*magenta*', '*brightmagenta*'),
  41. Generic.Error: ('brightred', 'brightred'),
  42. Error: ('_brightred_', '_brightred_'),
  43. }
  44. IRC_COLOR_MAP = {
  45. 'white': 0,
  46. 'black': 1,
  47. 'blue': 2,
  48. 'brightgreen': 3,
  49. 'brightred': 4,
  50. 'yellow': 5,
  51. 'magenta': 6,
  52. 'orange': 7,
  53. 'green': 7, #compat w/ ansi
  54. 'brightyellow': 8,
  55. 'lightgreen': 9,
  56. 'brightcyan': 9, # compat w/ ansi
  57. 'cyan': 10,
  58. 'lightblue': 11,
  59. 'red': 11, # compat w/ ansi
  60. 'brightblue': 12,
  61. 'brightmagenta': 13,
  62. 'brightblack': 14,
  63. 'gray': 15,
  64. }
  65. def ircformat(color, text):
  66. if len(color) < 1:
  67. return text
  68. add = sub = ''
  69. if '_' in color: # italic
  70. add += '\x1D'
  71. sub = '\x1D' + sub
  72. color = color.strip('_')
  73. if '*' in color: # bold
  74. add += '\x02'
  75. sub = '\x02' + sub
  76. color = color.strip('*')
  77. # underline (\x1F) not supported
  78. # backgrounds (\x03FF,BB) not supported
  79. if len(color) > 0: # actual color - may have issues with ircformat("red", "blah")+"10" type stuff
  80. add += '\x03' + str(IRC_COLOR_MAP[color]).zfill(2)
  81. sub = '\x03' + sub
  82. return add + text + sub
  83. return '<'+add+'>'+text+'</'+sub+'>'
  84. class IRCFormatter(Formatter):
  85. r"""
  86. Format tokens with IRC color sequences
  87. The `get_style_defs()` method doesn't do anything special since there is
  88. no support for common styles.
  89. Options accepted:
  90. `bg`
  91. Set to ``"light"`` or ``"dark"`` depending on the terminal's background
  92. (default: ``"light"``).
  93. `colorscheme`
  94. A dictionary mapping token types to (lightbg, darkbg) color names or
  95. ``None`` (default: ``None`` = use builtin colorscheme).
  96. `linenos`
  97. Set to ``True`` to have line numbers in the output as well
  98. (default: ``False`` = no line numbers).
  99. """
  100. name = 'IRC'
  101. aliases = ['irc', 'IRC']
  102. filenames = []
  103. def __init__(self, **options):
  104. Formatter.__init__(self, **options)
  105. self.darkbg = get_choice_opt(options, 'bg',
  106. ['light', 'dark'], 'light') == 'dark'
  107. self.colorscheme = options.get('colorscheme', None) or IRC_COLORS
  108. self.linenos = options.get('linenos', False)
  109. self._lineno = 0
  110. def _write_lineno(self, outfile):
  111. self._lineno += 1
  112. outfile.write("\n%04d: " % self._lineno)
  113. def _format_unencoded_with_lineno(self, tokensource, outfile):
  114. self._write_lineno(outfile)
  115. for ttype, value in tokensource:
  116. if value.endswith("\n"):
  117. self._write_lineno(outfile)
  118. value = value[:-1]
  119. color = self.colorscheme.get(ttype)
  120. while color is None:
  121. ttype = ttype[:-1]
  122. color = self.colorscheme.get(ttype)
  123. if color:
  124. color = color[self.darkbg]
  125. spl = value.split('\n')
  126. for line in spl[:-1]:
  127. self._write_lineno(outfile)
  128. if line:
  129. outfile.write(ircformat(color, line[:-1]))
  130. if spl[-1]:
  131. outfile.write(ircformat(color, spl[-1]))
  132. else:
  133. outfile.write(value)
  134. outfile.write("\n")
  135. def format_unencoded(self, tokensource, outfile):
  136. if self.linenos:
  137. self._format_unencoded_with_lineno(tokensource, outfile)
  138. return
  139. for ttype, value in tokensource:
  140. color = self.colorscheme.get(ttype)
  141. while color is None:
  142. ttype = ttype[:-1]
  143. color = self.colorscheme.get(ttype)
  144. if color:
  145. color = color[self.darkbg]
  146. spl = value.split('\n')
  147. for line in spl[:-1]:
  148. if line:
  149. outfile.write(ircformat(color, line))
  150. outfile.write('\n')
  151. if spl[-1]:
  152. outfile.write(ircformat(color, spl[-1]))
  153. else:
  154. outfile.write(value)