comparison doc/hgmanpage.py @ 43076:2372284d9457

formatting: blacken the codebase This is using my patch to black (https://github.com/psf/black/pull/826) so we don't un-wrap collection literals. Done with: hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S # skip-blame mass-reformatting only # no-check-commit reformats foo_bar functions Differential Revision: https://phab.mercurial-scm.org/D6971
author Augie Fackler <augie@google.com>
date Sun, 06 Oct 2019 09:45:02 -0400
parents 93a1a4fef532
children 89a2afe31e82
comparison
equal deleted inserted replaced
43075:57875cf423c9 43076:2372284d9457
51 from docutils import ( 51 from docutils import (
52 languages, 52 languages,
53 nodes, 53 nodes,
54 writers, 54 writers,
55 ) 55 )
56
56 try: 57 try:
57 import roman 58 import roman
58 except ImportError: 59 except ImportError:
59 from docutils.utils import roman 60 from docutils.utils import roman
60 61
63 OPTION_LIST_INDENT = 7 64 OPTION_LIST_INDENT = 7
64 BLOCKQOUTE_INDENT = 3.5 65 BLOCKQOUTE_INDENT = 3.5
65 66
66 # Define two macros so man/roff can calculate the 67 # Define two macros so man/roff can calculate the
67 # indent/unindent margins by itself 68 # indent/unindent margins by itself
68 MACRO_DEF = (r""". 69 MACRO_DEF = r""".
69 .nr rst2man-indent-level 0 70 .nr rst2man-indent-level 0
70 . 71 .
71 .de1 rstReportMargin 72 .de1 rstReportMargin
72 \\$1 \\n[an-margin] 73 \\$1 \\n[an-margin]
73 level \\n[rst2man-indent-level] 74 level \\n[rst2man-indent-level]
90 .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] 91 .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
91 .nr rst2man-indent-level -1 92 .nr rst2man-indent-level -1
92 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] 93 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
93 .in \\n[rst2man-indent\\n[rst2man-indent-level]]u 94 .in \\n[rst2man-indent\\n[rst2man-indent-level]]u
94 .. 95 ..
95 """) 96 """
97
96 98
97 class Writer(writers.Writer): 99 class Writer(writers.Writer):
98 100
99 supported = ('manpage') 101 supported = 'manpage'
100 """Formats this writer supports.""" 102 """Formats this writer supports."""
101 103
102 output = None 104 output = None
103 """Final translated form of `document`.""" 105 """Final translated form of `document`."""
104 106
116 def __init__(self): 118 def __init__(self):
117 self._rows = [] 119 self._rows = []
118 self._options = ['center'] 120 self._options = ['center']
119 self._tab_char = '\t' 121 self._tab_char = '\t'
120 self._coldefs = [] 122 self._coldefs = []
123
121 def new_row(self): 124 def new_row(self):
122 self._rows.append([]) 125 self._rows.append([])
126
123 def append_separator(self, separator): 127 def append_separator(self, separator):
124 """Append the separator for table head.""" 128 """Append the separator for table head."""
125 self._rows.append([separator]) 129 self._rows.append([separator])
130
126 def append_cell(self, cell_lines): 131 def append_cell(self, cell_lines):
127 """cell_lines is an array of lines""" 132 """cell_lines is an array of lines"""
128 start = 0 133 start = 0
129 if len(cell_lines) > 0 and cell_lines[0] == '.sp\n': 134 if len(cell_lines) > 0 and cell_lines[0] == '.sp\n':
130 start = 1 135 start = 1
131 self._rows[-1].append(cell_lines[start:]) 136 self._rows[-1].append(cell_lines[start:])
132 if len(self._coldefs) < len(self._rows[-1]): 137 if len(self._coldefs) < len(self._rows[-1]):
133 self._coldefs.append('l') 138 self._coldefs.append('l')
139
134 def _minimize_cell(self, cell_lines): 140 def _minimize_cell(self, cell_lines):
135 """Remove leading and trailing blank and ``.sp`` lines""" 141 """Remove leading and trailing blank and ``.sp`` lines"""
136 while (cell_lines and cell_lines[0] in ('\n', '.sp\n')): 142 while cell_lines and cell_lines[0] in ('\n', '.sp\n'):
137 del cell_lines[0] 143 del cell_lines[0]
138 while (cell_lines and cell_lines[-1] in ('\n', '.sp\n')): 144 while cell_lines and cell_lines[-1] in ('\n', '.sp\n'):
139 del cell_lines[-1] 145 del cell_lines[-1]
146
140 def as_list(self): 147 def as_list(self):
141 text = ['.TS\n'] 148 text = ['.TS\n']
142 text.append(' '.join(self._options) + ';\n') 149 text.append(' '.join(self._options) + ';\n')
143 text.append('|%s|.\n' % ('|'.join(self._coldefs))) 150 text.append('|%s|.\n' % ('|'.join(self._coldefs)))
144 for row in self._rows: 151 for row in self._rows:
145 # row = array of cells. cell = array of lines. 152 # row = array of cells. cell = array of lines.
146 text.append('_\n') # line above 153 text.append('_\n') # line above
147 text.append('T{\n') 154 text.append('T{\n')
148 for i in range(len(row)): 155 for i in range(len(row)):
149 cell = row[i] 156 cell = row[i]
150 self._minimize_cell(cell) 157 self._minimize_cell(cell)
151 text.extend(cell) 158 text.extend(cell)
152 if not text[-1].endswith('\n'): 159 if not text[-1].endswith('\n'):
153 text[-1] += '\n' 160 text[-1] += '\n'
154 if i < len(row) - 1: 161 if i < len(row) - 1:
155 text.append('T}'+self._tab_char+'T{\n') 162 text.append('T}' + self._tab_char + 'T{\n')
156 else: 163 else:
157 text.append('T}\n') 164 text.append('T}\n')
158 text.append('_\n') 165 text.append('_\n')
159 text.append('.TE\n') 166 text.append('.TE\n')
160 return text 167 return text
168
161 169
162 class Translator(nodes.NodeVisitor): 170 class Translator(nodes.NodeVisitor):
163 """""" 171 """"""
164 172
165 words_and_spaces = re.compile(r'\S+| +|\n') 173 words_and_spaces = re.compile(r'\S+| +|\n')
169 nodes.NodeVisitor.__init__(self, document) 177 nodes.NodeVisitor.__init__(self, document)
170 self.settings = settings = document.settings 178 self.settings = settings = document.settings
171 lcode = settings.language_code 179 lcode = settings.language_code
172 arglen = len(inspect.getargspec(languages.get_language)[0]) 180 arglen = len(inspect.getargspec(languages.get_language)[0])
173 if arglen == 2: 181 if arglen == 2:
174 self.language = languages.get_language(lcode, 182 self.language = languages.get_language(
175 self.document.reporter) 183 lcode, self.document.reporter
184 )
176 else: 185 else:
177 self.language = languages.get_language(lcode) 186 self.language = languages.get_language(lcode)
178 self.head = [] 187 self.head = []
179 self.body = [] 188 self.body = []
180 self.foot = [] 189 self.foot = []
187 # the list style "*" bullet or "#" numbered 196 # the list style "*" bullet or "#" numbered
188 self._list_char = [] 197 self._list_char = []
189 # writing the header .TH and .SH NAME is postboned after 198 # writing the header .TH and .SH NAME is postboned after
190 # docinfo. 199 # docinfo.
191 self._docinfo = { 200 self._docinfo = {
192 "title" : "", "title_upper": "", 201 "title": "",
193 "subtitle" : "", 202 "title_upper": "",
194 "manual_section" : "", "manual_group" : "", 203 "subtitle": "",
195 "author" : [], 204 "manual_section": "",
196 "date" : "", 205 "manual_group": "",
197 "copyright" : "", 206 "author": [],
198 "version" : "", 207 "date": "",
199 } 208 "copyright": "",
200 self._docinfo_keys = [] # a list to keep the sequence as in source. 209 "version": "",
201 self._docinfo_names = {} # to get name from text not normalized. 210 }
211 self._docinfo_keys = [] # a list to keep the sequence as in source.
212 self._docinfo_names = {} # to get name from text not normalized.
202 self._in_docinfo = None 213 self._in_docinfo = None
203 self._active_table = None 214 self._active_table = None
204 self._in_literal = False 215 self._in_literal = False
205 self.header_written = 0 216 self.header_written = 0
206 self._line_block = 0 217 self._line_block = 0
215 # Fonts are put on a stack, the top one is used. 226 # Fonts are put on a stack, the top one is used.
216 # ``.ft P`` or ``\\fP`` pop from stack. 227 # ``.ft P`` or ``\\fP`` pop from stack.
217 # ``B`` bold, ``I`` italic, ``R`` roman should be available. 228 # ``B`` bold, ``I`` italic, ``R`` roman should be available.
218 # Hopefully ``C`` courier too. 229 # Hopefully ``C`` courier too.
219 self.defs = { 230 self.defs = {
220 'indent' : ('.INDENT %.1f\n', '.UNINDENT\n'), 231 'indent': ('.INDENT %.1f\n', '.UNINDENT\n'),
221 'definition_list_item' : ('.TP', ''), 232 'definition_list_item': ('.TP', ''),
222 'field_name' : ('.TP\n.B ', '\n'), 233 'field_name': ('.TP\n.B ', '\n'),
223 'literal' : ('\\fB', '\\fP'), 234 'literal': ('\\fB', '\\fP'),
224 'literal_block' : ('.sp\n.nf\n.ft C\n', '\n.ft P\n.fi\n'), 235 'literal_block': ('.sp\n.nf\n.ft C\n', '\n.ft P\n.fi\n'),
225 236 'option_list_item': ('.TP\n', ''),
226 'option_list_item' : ('.TP\n', ''), 237 'reference': (r'\%', r'\:'),
227 238 'emphasis': ('\\fI', '\\fP'),
228 'reference' : (r'\%', r'\:'), 239 'strong': ('\\fB', '\\fP'),
229 'emphasis': ('\\fI', '\\fP'), 240 'term': ('\n.B ', '\n'),
230 'strong' : ('\\fB', '\\fP'), 241 'title_reference': ('\\fI', '\\fP'),
231 'term' : ('\n.B ', '\n'), 242 'topic-title': ('.SS ',),
232 'title_reference' : ('\\fI', '\\fP'), 243 'sidebar-title': ('.SS ',),
233 244 'problematic': ('\n.nf\n', '\n.fi\n'),
234 'topic-title' : ('.SS ',), 245 }
235 'sidebar-title' : ('.SS ',),
236
237 'problematic' : ('\n.nf\n', '\n.fi\n'),
238 }
239 # NOTE don't specify the newline before a dot-command, but ensure 246 # NOTE don't specify the newline before a dot-command, but ensure
240 # it is there. 247 # it is there.
241 248
242 def comment_begin(self, text): 249 def comment_begin(self, text):
243 """Return commented version of the passed text WITHOUT end of 250 """Return commented version of the passed text WITHOUT end of
244 line/comment.""" 251 line/comment."""
245 prefix = '.\\" ' 252 prefix = '.\\" '
246 out_text = ''.join( 253 out_text = ''.join(
247 [(prefix + in_line + '\n') 254 [(prefix + in_line + '\n') for in_line in text.split('\n')]
248 for in_line in text.split('\n')]) 255 )
249 return out_text 256 return out_text
250 257
251 def comment(self, text): 258 def comment(self, text):
252 """Return commented version of the passed text.""" 259 """Return commented version of the passed text."""
253 return self.comment_begin(text)+'.\n' 260 return self.comment_begin(text) + '.\n'
254 261
255 def ensure_eol(self): 262 def ensure_eol(self):
256 """Ensure the last line in body is terminated by new line.""" 263 """Ensure the last line in body is terminated by new line."""
257 if self.body[-1][-1] != '\n': 264 if self.body[-1][-1] != '\n':
258 self.body.append('\n') 265 self.body.append('\n')
264 self.head.append(self.header()) 271 self.head.append(self.header())
265 # filter body 272 # filter body
266 for i in range(len(self.body) - 1, 0, -1): 273 for i in range(len(self.body) - 1, 0, -1):
267 # remove superfluous vertical gaps. 274 # remove superfluous vertical gaps.
268 if self.body[i] == '.sp\n': 275 if self.body[i] == '.sp\n':
269 if self.body[i - 1][:4] in ('.BI ','.IP '): 276 if self.body[i - 1][:4] in ('.BI ', '.IP '):
270 self.body[i] = '.\n' 277 self.body[i] = '.\n'
271 elif (self.body[i - 1][:3] == '.B ' and 278 elif (
272 self.body[i - 2][:4] == '.TP\n'): 279 self.body[i - 1][:3] == '.B '
280 and self.body[i - 2][:4] == '.TP\n'
281 ):
273 self.body[i] = '.\n' 282 self.body[i] = '.\n'
274 elif (self.body[i - 1] == '\n' and 283 elif (
275 self.body[i - 2][0] != '.' and 284 self.body[i - 1] == '\n'
276 (self.body[i - 3][:7] == '.TP\n.B ' 285 and self.body[i - 2][0] != '.'
277 or self.body[i - 3][:4] == '\n.B ') 286 and (
278 ): 287 self.body[i - 3][:7] == '.TP\n.B '
288 or self.body[i - 3][:4] == '\n.B '
289 )
290 ):
279 self.body[i] = '.\n' 291 self.body[i] = '.\n'
280 return ''.join(self.head + self.body + self.foot) 292 return ''.join(self.head + self.body + self.foot)
281 293
282 def deunicode(self, text): 294 def deunicode(self, text):
283 text = text.replace(u'\xa0', '\\ ') 295 text = text.replace(u'\xa0', '\\ ')
284 text = text.replace(u'\u2020', '\\(dg') 296 text = text.replace(u'\u2020', '\\(dg')
285 return text 297 return text
286 298
287 def visit_Text(self, node): 299 def visit_Text(self, node):
288 text = node.astext() 300 text = node.astext()
289 text = text.replace('\\','\\e') 301 text = text.replace('\\', '\\e')
290 replace_pairs = [ 302 replace_pairs = [
291 (u'-', u'\\-'), 303 (u'-', u'\\-'),
292 (u"'", u'\\(aq'), 304 (u"'", u'\\(aq'),
293 (u'´', u"\\'"), 305 (u'´', u"\\'"),
294 (u'`', u'\\(ga'), 306 (u'`', u'\\(ga'),
295 ] 307 ]
296 for (in_char, out_markup) in replace_pairs: 308 for (in_char, out_markup) in replace_pairs:
297 text = text.replace(in_char, out_markup) 309 text = text.replace(in_char, out_markup)
298 # unicode 310 # unicode
299 text = self.deunicode(text) 311 text = self.deunicode(text)
300 if self._in_literal: 312 if self._in_literal:
308 pass 320 pass
309 321
310 def list_start(self, node): 322 def list_start(self, node):
311 class enum_char(object): 323 class enum_char(object):
312 enum_style = { 324 enum_style = {
313 'bullet' : '\\(bu', 325 'bullet': '\\(bu',
314 'emdash' : '\\(em', 326 'emdash': '\\(em',
315 } 327 }
316 328
317 def __init__(self, style): 329 def __init__(self, style):
318 self._style = style 330 self._style = style
319 if 'start' in node: 331 if 'start' in node:
320 self._cnt = node['start'] - 1 332 self._cnt = node['start'] - 1
356 368
357 next = __next__ 369 next = __next__
358 370
359 def get_width(self): 371 def get_width(self):
360 return self._indent 372 return self._indent
373
361 def __repr__(self): 374 def __repr__(self):
362 return 'enum_style-%s' % list(self._style) 375 return 'enum_style-%s' % list(self._style)
363 376
364 if 'enumtype' in node: 377 if 'enumtype' in node:
365 self._list_char.append(enum_char(node['enumtype'])) 378 self._list_char.append(enum_char(node['enumtype']))
374 def list_end(self): 387 def list_end(self):
375 self.dedent() 388 self.dedent()
376 self._list_char.pop() 389 self._list_char.pop()
377 390
378 def header(self): 391 def header(self):
379 tmpl = (".TH %(title_upper)s %(manual_section)s" 392 tmpl = (
380 " \"%(date)s\" \"%(version)s\" \"%(manual_group)s\"\n" 393 ".TH %(title_upper)s %(manual_section)s"
381 ".SH NAME\n" 394 " \"%(date)s\" \"%(version)s\" \"%(manual_group)s\"\n"
382 "%(title)s \\- %(subtitle)s\n") 395 ".SH NAME\n"
396 "%(title)s \\- %(subtitle)s\n"
397 )
383 return tmpl % self._docinfo 398 return tmpl % self._docinfo
384 399
385 def append_header(self): 400 def append_header(self):
386 """append header with .TH and .SH NAME""" 401 """append header with .TH and .SH NAME"""
387 # NOTE before everything 402 # NOTE before everything
398 def depart_address(self, node): 413 def depart_address(self, node):
399 pass 414 pass
400 415
401 def visit_admonition(self, node, name=None): 416 def visit_admonition(self, node, name=None):
402 if name: 417 if name:
403 self.body.append('.IP %s\n' % 418 self.body.append('.IP %s\n' % self.language.labels.get(name, name))
404 self.language.labels.get(name, name))
405 419
406 def depart_admonition(self, node): 420 def depart_admonition(self, node):
407 self.body.append('.RE\n') 421 self.body.append('.RE\n')
408 422
409 def visit_attention(self, node): 423 def visit_attention(self, node):
468 482
469 def depart_citation(self, node): 483 def depart_citation(self, node):
470 pass 484 pass
471 485
472 def visit_citation_reference(self, node): 486 def visit_citation_reference(self, node):
473 self.body.append('['+node.astext()+']') 487 self.body.append('[' + node.astext() + ']')
474 raise nodes.SkipNode() 488 raise nodes.SkipNode()
475 489
476 def visit_classifier(self, node): 490 def visit_classifier(self, node):
477 pass 491 pass
478 492
484 498
485 def depart_colspec(self, node): 499 def depart_colspec(self, node):
486 pass 500 pass
487 501
488 def write_colspecs(self): 502 def write_colspecs(self):
489 self.body.append("%s.\n" % ('L '*len(self.colspecs))) 503 self.body.append("%s.\n" % ('L ' * len(self.colspecs)))
490 504
491 def visit_comment(self, node, 505 def visit_comment(self, node, sub=re.compile('-(?=-)').sub):
492 sub=re.compile('-(?=-)').sub):
493 self.body.append(self.comment(node.astext())) 506 self.body.append(self.comment(node.astext()))
494 raise nodes.SkipNode() 507 raise nodes.SkipNode()
495 508
496 def visit_contact(self, node): 509 def visit_contact(self, node):
497 self.visit_docinfo_item(node, 'contact') 510 self.visit_docinfo_item(node, 'contact')
567 self._in_literal = False 580 self._in_literal = False
568 self.body.append(self.defs['literal_block'][1]) 581 self.body.append(self.defs['literal_block'][1])
569 582
570 def visit_document(self, node): 583 def visit_document(self, node):
571 # no blank line between comment and header. 584 # no blank line between comment and header.
572 self.body.append(self.comment(self.document_start).rstrip()+'\n') 585 self.body.append(self.comment(self.document_start).rstrip() + '\n')
573 # writing header is postboned 586 # writing header is postboned
574 self.header_written = 0 587 self.header_written = 0
575 588
576 def depart_document(self, node): 589 def depart_document(self, node):
577 if self._docinfo['author']: 590 if self._docinfo['author']:
578 self.body.append('.SH AUTHOR\n%s\n' 591 self.body.append(
579 % ', '.join(self._docinfo['author'])) 592 '.SH AUTHOR\n%s\n' % ', '.join(self._docinfo['author'])
580 skip = ('author', 'copyright', 'date', 593 )
581 'manual_group', 'manual_section', 594 skip = (
582 'subtitle', 595 'author',
583 'title', 'title_upper', 'version') 596 'copyright',
597 'date',
598 'manual_group',
599 'manual_section',
600 'subtitle',
601 'title',
602 'title_upper',
603 'version',
604 )
584 for name in self._docinfo_keys: 605 for name in self._docinfo_keys:
585 if name == 'address': 606 if name == 'address':
586 self.body.append("\n%s:\n%s%s.nf\n%s\n.fi\n%s%s" % ( 607 self.body.append(
587 self.language.labels.get(name, name), 608 "\n%s:\n%s%s.nf\n%s\n.fi\n%s%s"
588 self.defs['indent'][0] % 0, 609 % (
589 self.defs['indent'][0] % BLOCKQOUTE_INDENT, 610 self.language.labels.get(name, name),
590 self._docinfo[name], 611 self.defs['indent'][0] % 0,
591 self.defs['indent'][1], 612 self.defs['indent'][0] % BLOCKQOUTE_INDENT,
592 self.defs['indent'][1])) 613 self._docinfo[name],
614 self.defs['indent'][1],
615 self.defs['indent'][1],
616 )
617 )
593 elif name not in skip: 618 elif name not in skip:
594 if name in self._docinfo_names: 619 if name in self._docinfo_names:
595 label = self._docinfo_names[name] 620 label = self._docinfo_names[name]
596 else: 621 else:
597 label = self.language.labels.get(name, name) 622 label = self.language.labels.get(name, name)
598 self.body.append("\n%s: %s\n" % (label, self._docinfo[name])) 623 self.body.append("\n%s: %s\n" % (label, self._docinfo[name]))
599 if self._docinfo['copyright']: 624 if self._docinfo['copyright']:
600 self.body.append('.SH COPYRIGHT\n%s\n' 625 self.body.append('.SH COPYRIGHT\n%s\n' % self._docinfo['copyright'])
601 % self._docinfo['copyright']) 626 self.body.append(
602 self.body.append(self.comment( 627 self.comment('Generated by docutils manpage writer.\n')
603 'Generated by docutils manpage writer.\n')) 628 )
604 629
605 def visit_emphasis(self, node): 630 def visit_emphasis(self, node):
606 self.body.append(self.defs['emphasis'][0]) 631 self.body.append(self.defs['emphasis'][0])
607 632
608 def depart_emphasis(self, node): 633 def depart_emphasis(self, node):
609 self.body.append(self.defs['emphasis'][1]) 634 self.body.append(self.defs['emphasis'][1])
610 635
611 def visit_entry(self, node): 636 def visit_entry(self, node):
612 # a cell in a table row 637 # a cell in a table row
613 if 'morerows' in node: 638 if 'morerows' in node:
614 self.document.reporter.warning('"table row spanning" not supported', 639 self.document.reporter.warning(
615 base_node=node) 640 '"table row spanning" not supported', base_node=node
641 )
616 if 'morecols' in node: 642 if 'morecols' in node:
617 self.document.reporter.warning( 643 self.document.reporter.warning(
618 '"table cell spanning" not supported', base_node=node) 644 '"table cell spanning" not supported', base_node=node
645 )
619 self.context.append(len(self.body)) 646 self.context.append(len(self.body))
620 647
621 def depart_entry(self, node): 648 def depart_entry(self, node):
622 start = self.context.pop() 649 start = self.context.pop()
623 self._active_table.append_cell(self.body[start:]) 650 self._active_table.append_cell(self.body[start:])
640 def depart_field(self, node): 667 def depart_field(self, node):
641 pass 668 pass
642 669
643 def visit_field_body(self, node): 670 def visit_field_body(self, node):
644 if self._in_docinfo: 671 if self._in_docinfo:
645 name_normalized = self._field_name.lower().replace(" ","_") 672 name_normalized = self._field_name.lower().replace(" ", "_")
646 self._docinfo_names[name_normalized] = self._field_name 673 self._docinfo_names[name_normalized] = self._field_name
647 self.visit_docinfo_item(node, name_normalized) 674 self.visit_docinfo_item(node, name_normalized)
648 raise nodes.SkipNode() 675 raise nodes.SkipNode()
649 676
650 def depart_field_body(self, node): 677 def depart_field_body(self, node):
673 def depart_figure(self, node): 700 def depart_figure(self, node):
674 self.dedent() 701 self.dedent()
675 self.dedent() 702 self.dedent()
676 703
677 def visit_footer(self, node): 704 def visit_footer(self, node):
678 self.document.reporter.warning('"footer" not supported', 705 self.document.reporter.warning('"footer" not supported', base_node=node)
679 base_node=node)
680 706
681 def depart_footer(self, node): 707 def depart_footer(self, node):
682 pass 708 pass
683 709
684 def visit_footnote(self, node): 710 def visit_footnote(self, node):
688 714
689 def depart_footnote(self, node): 715 def depart_footnote(self, node):
690 pass 716 pass
691 717
692 def footnote_backrefs(self, node): 718 def footnote_backrefs(self, node):
693 self.document.reporter.warning('"footnote_backrefs" not supported', 719 self.document.reporter.warning(
694 base_node=node) 720 '"footnote_backrefs" not supported', base_node=node
721 )
695 722
696 def visit_footnote_reference(self, node): 723 def visit_footnote_reference(self, node):
697 self.body.append('['+self.deunicode(node.astext())+']') 724 self.body.append('[' + self.deunicode(node.astext()) + ']')
698 raise nodes.SkipNode() 725 raise nodes.SkipNode()
699 726
700 def depart_footnote_reference(self, node): 727 def depart_footnote_reference(self, node):
701 pass 728 pass
702 729
734 761
735 def depart_attribution(self, node): 762 def depart_attribution(self, node):
736 self.body.append('\n') 763 self.body.append('\n')
737 764
738 def visit_image(self, node): 765 def visit_image(self, node):
739 self.document.reporter.warning('"image" not supported', 766 self.document.reporter.warning('"image" not supported', base_node=node)
740 base_node=node)
741 text = [] 767 text = []
742 if 'alt' in node.attributes: 768 if 'alt' in node.attributes:
743 text.append(node.attributes['alt']) 769 text.append(node.attributes['alt'])
744 if 'uri' in node.attributes: 770 if 'uri' in node.attributes:
745 text.append(node.attributes['uri']) 771 text.append(node.attributes['uri'])
751 777
752 depart_important = depart_admonition 778 depart_important = depart_admonition
753 779
754 def visit_label(self, node): 780 def visit_label(self, node):
755 # footnote and citation 781 # footnote and citation
756 if (isinstance(node.parent, nodes.footnote) 782 if isinstance(node.parent, nodes.footnote) or isinstance(
757 or isinstance(node.parent, nodes.citation)): 783 node.parent, nodes.citation
784 ):
758 raise nodes.SkipNode() 785 raise nodes.SkipNode()
759 self.document.reporter.warning('"unsupported "label"', 786 self.document.reporter.warning('"unsupported "label"', base_node=node)
760 base_node=node)
761 self.body.append('[') 787 self.body.append('[')
762 788
763 def depart_label(self, node): 789 def depart_label(self, node):
764 self.body.append(']\n') 790 self.body.append(']\n')
765 791
792 def depart_line(self, node): 818 def depart_line(self, node):
793 self.body.append('\n') 819 self.body.append('\n')
794 820
795 def visit_list_item(self, node): 821 def visit_list_item(self, node):
796 # man 7 man argues to use ".IP" instead of ".TP" 822 # man 7 man argues to use ".IP" instead of ".TP"
797 self.body.append('.IP %s %d\n' % ( 823 self.body.append(
798 next(self._list_char[-1]), 824 '.IP %s %d\n'
799 self._list_char[-1].get_width(),)) 825 % (next(self._list_char[-1]), self._list_char[-1].get_width(),)
826 )
800 827
801 def depart_list_item(self, node): 828 def depart_list_item(self, node):
802 pass 829 pass
803 830
804 def visit_literal(self, node): 831 def visit_literal(self, node):
853 # as one option could have several forms it is a group 880 # as one option could have several forms it is a group
854 # options without parameter bold only, .B, -v 881 # options without parameter bold only, .B, -v
855 # options with parameter bold italic, .BI, -f file 882 # options with parameter bold italic, .BI, -f file
856 # 883 #
857 # we do not know if .B or .BI 884 # we do not know if .B or .BI
858 self.context.append('.B') # blind guess 885 self.context.append('.B') # blind guess
859 self.context.append(len(self.body)) # to be able to insert later 886 self.context.append(len(self.body)) # to be able to insert later
860 self.context.append(0) # option counter 887 self.context.append(0) # option counter
861 888
862 def depart_option_group(self, node): 889 def depart_option_group(self, node):
863 self.context.pop() # the counter 890 self.context.pop() # the counter
864 start_position = self.context.pop() 891 start_position = self.context.pop()
865 text = self.body[start_position:] 892 text = self.body[start_position:]
883 910
884 def depart_option_string(self, node): 911 def depart_option_string(self, node):
885 pass 912 pass
886 913
887 def visit_option_argument(self, node): 914 def visit_option_argument(self, node):
888 self.context[-3] = '.BI' # bold/italic alternate 915 self.context[-3] = '.BI' # bold/italic alternate
889 if node['delimiter'] != ' ': 916 if node['delimiter'] != ' ':
890 self.body.append('\\fB%s ' % node['delimiter']) 917 self.body.append('\\fB%s ' % node['delimiter'])
891 elif self.body[len(self.body) - 1].endswith('='): 918 elif self.body[len(self.body) - 1].endswith('='):
892 # a blank only means no blank in output, just changing font 919 # a blank only means no blank in output, just changing font
893 self.body.append(' ') 920 self.body.append(' ')
966 def visit_substitution_definition(self, node): 993 def visit_substitution_definition(self, node):
967 """Internal only.""" 994 """Internal only."""
968 raise nodes.SkipNode() 995 raise nodes.SkipNode()
969 996
970 def visit_substitution_reference(self, node): 997 def visit_substitution_reference(self, node):
971 self.document.reporter.warning('"substitution_reference" not supported', 998 self.document.reporter.warning(
972 base_node=node) 999 '"substitution_reference" not supported', base_node=node
1000 )
973 1001
974 def visit_subtitle(self, node): 1002 def visit_subtitle(self, node):
975 if isinstance(node.parent, nodes.sidebar): 1003 if isinstance(node.parent, nodes.sidebar):
976 self.body.append(self.defs['strong'][0]) 1004 self.body.append(self.defs['strong'][0])
977 elif isinstance(node.parent, nodes.document): 1005 elif isinstance(node.parent, nodes.document):
979 elif isinstance(node.parent, nodes.section): 1007 elif isinstance(node.parent, nodes.section):
980 self.body.append(self.defs['strong'][0]) 1008 self.body.append(self.defs['strong'][0])
981 1009
982 def depart_subtitle(self, node): 1010 def depart_subtitle(self, node):
983 # document subtitle calls SkipNode 1011 # document subtitle calls SkipNode
984 self.body.append(self.defs['strong'][1]+'\n.PP\n') 1012 self.body.append(self.defs['strong'][1] + '\n.PP\n')
985 1013
986 def visit_system_message(self, node): 1014 def visit_system_message(self, node):
987 # TODO add report_level 1015 # TODO add report_level
988 #if node['level'] < self.document.reporter['writer'].report_level: 1016 # if node['level'] < self.document.reporter['writer'].report_level:
989 # Level is too low to display: 1017 # Level is too low to display:
990 # raise nodes.SkipNode 1018 # raise nodes.SkipNode
991 attr = {} 1019 attr = {}
992 if node.hasattr('id'): 1020 if node.hasattr('id'):
993 attr['name'] = node['id'] 1021 attr['name'] = node['id']
994 if node.hasattr('line'): 1022 if node.hasattr('line'):
995 line = ', line %s' % node['line'] 1023 line = ', line %s' % node['line']
996 else: 1024 else:
997 line = '' 1025 line = ''
998 self.body.append('.IP "System Message: %s/%s (%s:%s)"\n' 1026 self.body.append(
999 % (node['type'], node['level'], node['source'], line)) 1027 '.IP "System Message: %s/%s (%s:%s)"\n'
1028 % (node['type'], node['level'], node['source'], line)
1029 )
1000 1030
1001 def depart_system_message(self, node): 1031 def depart_system_message(self, node):
1002 pass 1032 pass
1003 1033
1004 def visit_table(self, node): 1034 def visit_table(self, node):
1109 self.visit_admonition(node, 'warning') 1139 self.visit_admonition(node, 'warning')
1110 1140
1111 depart_warning = depart_admonition 1141 depart_warning = depart_admonition
1112 1142
1113 def unimplemented_visit(self, node): 1143 def unimplemented_visit(self, node):
1114 raise NotImplementedError('visiting unimplemented node type: %s' 1144 raise NotImplementedError(
1115 % node.__class__.__name__) 1145 'visiting unimplemented node type: %s' % node.__class__.__name__
1146 )
1147
1116 1148
1117 # vim: set fileencoding=utf-8 et ts=4 ai : 1149 # vim: set fileencoding=utf-8 et ts=4 ai :