codekingpro/portable-devtools
114k
1"""2 pygments.formatters.groff3 ~~~~~~~~~~~~~~~~~~~~~~~~~4 5 Formatter for groff output.6 7 :copyright: Copyright 2006-present by the Pygments team, see AUTHORS.8 :license: BSD, see LICENSE for details.9"""10 11import math12from pygments.formatter import Formatter13from pygments.util import get_bool_opt, get_int_opt14 15__all__ = ['GroffFormatter']16 17 18class GroffFormatter(Formatter):19 """20 Format tokens with groff escapes to change their color and font style.21 22 .. versionadded:: 2.1123 24 Additional options accepted:25 26 `style`27 The style to use, can be a string or a Style subclass (default:28 ``'default'``).29 30 `monospaced`31 If set to true, monospace font will be used (default: ``true``).32 33 `linenos`34 If set to true, print the line numbers (default: ``false``).35 36 `wrap`37 Wrap lines to the specified number of characters. Disabled if set to 038 (default: ``0``).39 """40 41 name = 'groff'42 aliases = ['groff','troff','roff']43 filenames = []44 45 def __init__(self, **options):46 Formatter.__init__(self, **options)47 48 self.monospaced = get_bool_opt(options, 'monospaced', True)49 self.linenos = get_bool_opt(options, 'linenos', False)50 self._lineno = 051 self.wrap = get_int_opt(options, 'wrap', 0)52 self._linelen = 053 54 self.styles = {}55 self._make_styles()56 57 58 def _make_styles(self):59 regular = '\\f[CR]' if self.monospaced else '\\f[R]'60 bold = '\\f[CB]' if self.monospaced else '\\f[B]'61 italic = '\\f[CI]' if self.monospaced else '\\f[I]'62 63 for ttype, ndef in self.style:64 start = end = ''65 if ndef['color']:66 start += '\\m[{}]'.format(ndef['color'])67 end = '\\m[]' + end68 if ndef['bold']:69 start += bold70 end = regular + end71 if ndef['italic']:72 start += italic73 end = regular + end74 if ndef['bgcolor']:75 start += '\\M[{}]'.format(ndef['bgcolor'])76 end = '\\M[]' + end77 78 self.styles[ttype] = start, end79 80 81 def _define_colors(self, outfile):82 colors = set()83 for _, ndef in self.style:84 if ndef['color'] is not None:85 colors.add(ndef['color'])86 87 for color in sorted(colors):88 outfile.write('.defcolor ' + color + ' rgb #' + color + '\n')89 90 91 def _write_lineno(self, outfile):92 self._lineno += 193 outfile.write("%s% 4d " % (self._lineno != 1 and '\n' or '', self._lineno))94 95 96 def _wrap_line(self, line):97 length = len(line.rstrip('\n'))98 space = ' ' if self.linenos else ''99 newline = ''100 101 if length > self.wrap:102 for i in range(0, math.floor(length / self.wrap)):103 chunk = line[i*self.wrap:i*self.wrap+self.wrap]104 newline += (chunk + '\n' + space)105 remainder = length % self.wrap106 if remainder > 0:107 newline += line[-remainder-1:]108 self._linelen = remainder109 elif self._linelen + length > self.wrap:110 newline = ('\n' + space) + line111 self._linelen = length112 else:113 newline = line114 self._linelen += length115 116 return newline117 118 119 def _escape_chars(self, text):120 text = text.replace('\\', '\\[u005C]'). \121 replace('.', '\\[char46]'). \122 replace('\'', '\\[u0027]'). \123 replace('`', '\\[u0060]'). \124 replace('~', '\\[u007E]')125 copy = text126 127 for char in copy:128 if len(char) != len(char.encode()):129 uni = char.encode('unicode_escape') \130 .decode()[1:] \131 .replace('x', 'u00') \132 .upper()133 text = text.replace(char, '\\[u' + uni[1:] + ']')134 135 return text136 137 138 def format_unencoded(self, tokensource, outfile):139 self._define_colors(outfile)140 141 outfile.write('.nf\n\\f[CR]\n')142 143 if self.linenos:144 self._write_lineno(outfile)145 146 for ttype, value in tokensource:147 while ttype not in self.styles:148 ttype = ttype.parent149 start, end = self.styles[ttype]150 151 for line in value.splitlines(True):152 if self.wrap > 0:153 line = self._wrap_line(line)154 155 if start and end:156 text = self._escape_chars(line.rstrip('\n'))157 if text != '':158 outfile.write(''.join((start, text, end)))159 else:160 outfile.write(self._escape_chars(line.rstrip('\n')))161 162 if line.endswith('\n'):163 if self.linenos:164 self._write_lineno(outfile)165 self._linelen = 0166 else:167 outfile.write('\n')168 self._linelen = 0169 170 outfile.write('\n.fi')171 