Viewing file: groff.py (4.99 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
""" pygments.formatters.groff ~~~~~~~~~~~~~~~~~~~~~~~~~
Formatter for groff output.
:copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """
import math from pip._vendor.pygments.formatter import Formatter from pip._vendor.pygments.util import get_bool_opt, get_int_opt
__all__ = ['GroffFormatter']
class GroffFormatter(Formatter): """ Format tokens with groff escapes to change their color and font style.
.. versionadded:: 2.11
Additional options accepted:
`style` The style to use, can be a string or a Style subclass (default: ``'default'``).
`monospaced` If set to true, monospace font will be used (default: ``true``).
`linenos` If set to true, print the line numbers (default: ``false``).
`wrap` Wrap lines to the specified number of characters. Disabled if set to 0 (default: ``0``). """
name = 'groff' aliases = ['groff','troff','roff'] filenames = []
def __init__(self, **options): Formatter.__init__(self, **options)
self.monospaced = get_bool_opt(options, 'monospaced', True) self.linenos = get_bool_opt(options, 'linenos', False) self._lineno = 0 self.wrap = get_int_opt(options, 'wrap', 0) self._linelen = 0
self.styles = {} self._make_styles()
def _make_styles(self): regular = '\\f[CR]' if self.monospaced else '\\f[R]' bold = '\\f[CB]' if self.monospaced else '\\f[B]' italic = '\\f[CI]' if self.monospaced else '\\f[I]'
for ttype, ndef in self.style: start = end = '' if ndef['color']: start += '\\m[{}]'.format(ndef['color']) end = '\\m[]' + end if ndef['bold']: start += bold end = regular + end if ndef['italic']: start += italic end = regular + end if ndef['bgcolor']: start += '\\M[{}]'.format(ndef['bgcolor']) end = '\\M[]' + end
self.styles[ttype] = start, end
def _define_colors(self, outfile): colors = set() for _, ndef in self.style: if ndef['color'] is not None: colors.add(ndef['color'])
for color in sorted(colors): outfile.write('.defcolor ' + color + ' rgb #' + color + '\n')
def _write_lineno(self, outfile): self._lineno += 1 outfile.write("%s% 4d " % (self._lineno != 1 and '\n' or '', self._lineno))
def _wrap_line(self, line): length = len(line.rstrip('\n')) space = ' ' if self.linenos else '' newline = ''
if length > self.wrap: for i in range(0, math.floor(length / self.wrap)): chunk = line[i*self.wrap:i*self.wrap+self.wrap] newline += (chunk + '\n' + space) remainder = length % self.wrap if remainder > 0: newline += line[-remainder-1:] self._linelen = remainder elif self._linelen + length > self.wrap: newline = ('\n' + space) + line self._linelen = length else: newline = line self._linelen += length
return newline
def _escape_chars(self, text): text = text.replace('\\', '\\[u005C]'). \ replace('.', '\\[char46]'). \ replace('\'', '\\[u0027]'). \ replace('`', '\\[u0060]'). \ replace('~', '\\[u007E]') copy = text
for char in copy: if len(char) != len(char.encode()): uni = char.encode('unicode_escape') \ .decode()[1:] \ .replace('x', 'u00') \ .upper() text = text.replace(char, '\\[u' + uni[1:] + ']')
return text
def format_unencoded(self, tokensource, outfile): self._define_colors(outfile)
outfile.write('.nf\n\\f[CR]\n')
if self.linenos: self._write_lineno(outfile)
for ttype, value in tokensource: while ttype not in self.styles: ttype = ttype.parent start, end = self.styles[ttype]
for line in value.splitlines(True): if self.wrap > 0: line = self._wrap_line(line)
if start and end: text = self._escape_chars(line.rstrip('\n')) if text != '': outfile.write(''.join((start, text, end))) else: outfile.write(self._escape_chars(line.rstrip('\n')))
if line.endswith('\n'): if self.linenos: self._write_lineno(outfile) self._linelen = 0 else: outfile.write('\n') self._linelen = 0
outfile.write('\n.fi')
|