def depart_title(self, node): if isinstance(node.parent, nodes.section): char = self._title_char else: char = '=' text = ''.join(x[1] for x in self.states.pop() if x[0] == -1) self.stateindent.pop() if self.sectionlevel == 1: self.states[-1].append( (0, ['%s' % ('=' * column_width(text)), text, '%s' % ('=' * column_width(text)), ''])) else: self.states[-1].append( (0, ['', text, '%s' % (char * column_width(text)), '']))
def _wrap_chunks(self, chunks): # type: (List[unicode]) -> List[unicode] """_wrap_chunks(chunks : [string]) -> [string] The original _wrap_chunks uses len() to calculate width. This method respects wide/fullwidth characters for width adjustment. """ drop_whitespace = getattr(self, 'drop_whitespace', True) # py25 compat lines = [] # type: List[unicode] if self.width <= 0: raise ValueError("invalid width %r (must be > 0)" % self.width) chunks.reverse() while chunks: cur_line = [] cur_len = 0 if lines: indent = self.subsequent_indent else: indent = self.initial_indent width = self.width - column_width(indent) if drop_whitespace and chunks[-1].strip() == '' and lines: del chunks[-1] while chunks: l = column_width(chunks[-1]) if cur_len + l <= width: cur_line.append(chunks.pop()) cur_len += l else: break if chunks and column_width(chunks[-1]) > width: self._handle_long_word(chunks, cur_line, cur_len, width) if drop_whitespace and cur_line and cur_line[-1].strip() == '': del cur_line[-1] if cur_line: lines.append(indent + ''.join(cur_line)) return lines
def validate_punctuation_mark(node): """ If text include ascii punctuation mark (.,) emit warning. :param docutils.nodes.Node node: node to validate. :return: list of validation error messages :rtype: List[ValidationErrorMessage] """ text = node.astext() if not text: return [] if column_width(text) == len(text): return [] # replace . with 。 text = sub_dot_space(u'\\1。', text) # ドット+スペース text = sub_dot_newline(u'\\1。\n', text) # ドット+改行 text = sub_dot_eol(u'\\1。', text) # ドット+終端 # replace , with 、 text = sub_comma_space(u'\\1、', text) # カンマ+スペース text = sub_comma_newline(u'\\1、\n', text) # カンマ+改行 text = sub_comma_eol(u'\\1、', text) # カンマ+終端 msgs = [] if text != node.astext(): msg = ValidationErrorMessage('ASCII punctuation mark', node, node.astext(), text) msgs.append(msg) return msgs
def test_maxwitdh_with_prefix(app): long_string = u' '.join([u"ham"] * 30) contents = ( u".. seealso:: %(long_string)s\n\n" u"* %(long_string)s\n" u"* %(long_string)s\n" u"\nspam egg\n" ) % locals() (app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8') app.builder.build_all() result = (app.outdir / 'contents.txt').text(encoding='utf-8') lines = result.splitlines() line_widths = [column_width(line) for line in lines] assert max(line_widths) < MAXWIDTH assert lines[0].startswith('See also: ham') assert lines[1].startswith(' ham') assert lines[2] == '' assert lines[3].startswith('* ham') assert lines[4].startswith(' ham') assert lines[5] == '' assert lines[6].startswith('* ham') assert lines[7].startswith(' ham') assert lines[8] == '' assert lines[9].startswith('spam egg')
def end_state(self, wrap=True, end=[''], first=None): content = self.states.pop() maxindent = sum(self.stateindent) indent = self.stateindent.pop() width = MAXWIDTH - (maxindent if not first else column_width(first)) # print("\nend-state -----\n", content) result = [] toformat = [] def do_format(): if not toformat: return if wrap: res = self.wrap(''.join(toformat), width=width) else: res = ''.join(toformat).splitlines() if end: res += end result.append((indent, res)) for itemindent, item in content: if itemindent == -1: toformat.append(item) else: do_format() result.append((indent + itemindent, item)) toformat = [] do_format() if first is not None and result: itemindent, item = result[0] if item: result.insert(0, (itemindent - indent, [first + item[0]])) result[1] = (itemindent, item[1:]) self.states[-1].extend(result)
def build_header(title, date, author, categories, tags, slug, status=None, attachments=None): """Build a header from a list of fields""" from docutils.utils import column_width header = '%s\n%s\n' % (title, '#' * column_width(title)) if date: header += ':date: %s\n' % date if author: header += ':author: %s\n' % author if categories: header += ':category: %s\n' % ', '.join(categories) if tags: header += ':tags: %s\n' % ', '.join(tags) if slug: header += ':slug: %s\n' % slug if status: header += ':status: %s\n' % status if attachments: header += ':attachments: %s\n' % ', '.join(attachments) header += '\n' return header
def depart_title(self, node): if isinstance(node.parent, nodes.section): char = self._title_char else: char = "^" text = "".join(x[1] for x in self.states.pop() if x[0] == -1) self.stateindent.pop() self.states[-1].append((0, ["", text, "%s" % (char * column_width(text)), ""]))
def depart_desc_signature(self, node): if node.parent["objtype"] in ("class", "exception", "method", "function"): self.add_text("**") else: self.add_text("``") text = "".join(x[1] for x in self.states.pop() if x[0] == -1) self.states.append([(0, ["", text, "-" * column_width(text)])]) self.end_state()
def header(self, text, level, raw=None): """Rendering header/heading tags like ``<h1>`` ``<h2>``. :param text: rendered text content for the header. :param level: a number for the header level, for example: 1. :param raw: raw text content of the header. """ return "\n{0}\n{1}\n".format(text, self.hmarks[level] * column_width(text))
def depart_title(self, node): if isinstance(node.parent, nodes.section): char = self._title_char else: char = '^' text = ''.join(x[1] for x in self.states.pop() if x[0] == -1) self.stateindent.pop() self.states[-1].append( (0, ['', text, '%s' % (char * column_width(text)), '']))
def depart_table(self, node): # type: (nodes.Node) -> None lines = None # type: List[unicode] lines = self.table[1:] # type: ignore fmted_rows = [] # type: List[List[List[unicode]]] colwidths = None # type: List[int] colwidths = self.table[0] # type: ignore realwidths = colwidths[:] separator = 0 # don't allow paragraphs in table cells for now for line in lines: if line == 'sep': separator = len(fmted_rows) else: cells = [] # type: List[List[unicode]] for i, cell in enumerate(line): par = my_wrap(cell, width=colwidths[i]) if par: maxwidth = max(column_width(x) for x in par) else: maxwidth = 0 realwidths[i] = max(realwidths[i], maxwidth) cells.append(par) fmted_rows.append(cells) def writesep(char='-'): # type: (unicode) -> None out = ['+'] # type: List[unicode] for width in realwidths: out.append(char * (width + 2)) out.append('+') self.add_text(''.join(out) + self.nl) def writerow(row): # type: (List[List[unicode]]) -> None lines = zip_longest(*row) for line in lines: out = ['|'] for i, cell in enumerate(line): if cell: adjust_len = len(cell) - column_width(cell) out.append(' ' + cell.ljust(realwidths[i] + 1 + adjust_len)) else: out.append(' ' * (realwidths[i] + 2)) out.append('|') self.add_text(''.join(out) + self.nl) for i, row in enumerate(fmted_rows): if separator and i == separator: writesep('=') else: writesep('-') writerow(row) writesep('-') self.table = None self.end_state(wrap=False)
def depart_table(self, node): # type: (nodes.Node) -> None lines = None # type: List[unicode] lines = self.table[1:] # type: ignore fmted_rows = [] # type: List[List[List[unicode]]] colwidths = None # type: List[int] colwidths = self.table[0] # type: ignore realwidths = colwidths[:] separator = 0 # don't allow paragraphs in table cells for now for line in lines: if line == 'sep': separator = len(fmted_rows) else: cells = [] # type: List[List[unicode]] for i, cell in enumerate(line): par = my_wrap(cell, width=colwidths[i]) if par: maxwidth = max(column_width(x) for x in par) else: maxwidth = 0 realwidths[i] = max(realwidths[i], maxwidth) cells.append(par) fmted_rows.append(cells) def writesep(char='-'): # type: (unicode) -> None out = ['+'] # type: List[unicode] for width in realwidths: out.append(char * (width+2)) out.append('+') self.add_text(''.join(out) + self.nl) def writerow(row): # type: (list[List[unicode]]) -> None lines = zip_longest(*row) for line in lines: out = ['|'] for i, cell in enumerate(line): if cell: adjust_len = len(cell) - column_width(cell) out.append(' ' + cell.ljust( realwidths[i] + 1 + adjust_len)) else: out.append(' ' * (realwidths[i] + 2)) out.append('|') self.add_text(''.join(out) + self.nl) for i, row in enumerate(fmted_rows): if separator and i == separator: writesep('=') else: writesep('-') writerow(row) writesep('-') self.table = None self.end_state(wrap=False)
def header(self, text, level, raw=None): """Rendering header/heading tags like ``<h1>`` ``<h2>``. :param text: rendered text content for the header. :param level: a number for the header level, for example: 1. :param raw: raw text content of the header. """ return '\n{0}\n{1}\n'.format(text, self.hmarks[level] * column_width(text))
def depart_table(self, node): # pylint: disable=R0912 # Many local variables are the way this was written # pylint: disable=R0914 lines = self.table[1:] fmted_rows = [] colwidths = self.table[0] realwidths = colwidths[:] separator = 0 for line in lines: if line == 'sep': separator = len(fmted_rows) else: cells = [] for i, cell in enumerate(line): par = TextWrapper(width=colwidths[i]).wrap(cell) if par: # Originally written to use map maxwidth = max([column_width(x) for x in par]) else: maxwidth = 0 realwidths[i] = max(realwidths[i], maxwidth) cells.append(par) fmted_rows.append(cells) def writesep(char='-'): out = ['+'] for width in realwidths: out.append(char * (width + 2)) out.append('+') self.add_text(''.join(out) + self.nl) def writerow(row): # Originally written to use *magic lines = zip(*row) for line in lines: out = ['|'] for i, cell in enumerate(line): if cell: adjust_len = len(cell) - column_width(cell) out.append(' ' + cell.ljust(realwidths[i] + 1 + adjust_len)) else: out.append(' ' * (realwidths[i] + 2)) out.append('|') self.add_text(''.join(out) + self.nl) for i, row in enumerate(fmted_rows): if separator and i == separator: writesep('=') else: writesep('-') writerow(row) writesep('-') self.table = None self.end_state(wrap=False)
def __str__(self): out = [] self.rewrap() def writesep(char="-", lineno=None): # type: (str, Optional[int]) -> str """Called on the line *before* lineno. Called with no *lineno* for the last sep. """ out = [] # type: List[str] for colno, width in enumerate(self.measured_widths): if ( lineno is not None and lineno > 0 and self[lineno, colno] is self[lineno - 1, colno] ): out.append(" " * (width + 2)) else: out.append(char * (width + 2)) head = "+" if out[0][0] == "-" else "|" tail = "+" if out[-1][0] == "-" else "|" glue = [ "+" if left[0] == "-" or right[0] == "-" else "|" for left, right in zip(out, out[1:]) ] glue.append(tail) return head + "".join(chain(*zip(out, glue))) for lineno, line in enumerate(self.lines): if self.separator and lineno == self.separator: out.append(writesep("=", lineno)) else: out.append(writesep("-", lineno)) for physical_line in range(self.physical_lines_for_line(line)): linestr = ["|"] for colno, cell in enumerate(line): if cell.col != colno: continue if lineno != cell.row: physical_text = "" elif physical_line >= len(cell.wrapped): physical_text = "" else: physical_text = cell.wrapped[physical_line] adjust_len = len(physical_text) - column_width(physical_text) linestr.append( " " + physical_text.ljust( self.cell_width(cell, self.measured_widths) + 1 + adjust_len ) + "|" ) out.append("".join(linestr)) out.append(writesep("-")) return "\n".join(out)
def depart_table(self, node): # pylint: disable=R0912 # Many local variables are the way this was written # pylint: disable=R0914 lines = self.table[1:] fmted_rows = [] colwidths = self.table[0] realwidths = colwidths[:] separator = 0 for line in lines: if line == 'sep': separator = len(fmted_rows) else: cells = [] for i, cell in enumerate(line): par = TextWrapper(width=colwidths[i]).wrap(cell) if par: # Originally written to use map maxwidth = max([column_width(x) for x in par]) else: maxwidth = 0 realwidths[i] = max(realwidths[i], maxwidth) cells.append(par) fmted_rows.append(cells) def writesep(char='-'): out = ['+'] for width in realwidths: out.append(char * (width + 2)) out.append('+') self.add_text(''.join(out) + self.nl) def writerow(row): # Originally written to use *magic lines = zip(*row) for line in lines: out = ['|'] for i, cell in enumerate(line): if cell: adjust_len = len(cell) - column_width(cell) out.append(' ' + cell.ljust( realwidths[i] + 1 + adjust_len)) else: out.append(' ' * (realwidths[i] + 2)) out.append('|') self.add_text(''.join(out) + self.nl) for i, row in enumerate(fmted_rows): if separator and i == separator: writesep('=') else: writesep('-') writerow(row) writesep('-') self.table = None self.end_state(wrap=False)
def _break_word(self, word, space_left): """_break_word(word : string, space_left : int) -> (string, string) Break line by unicode width instead of len(word). """ total = 0 for i, c in enumerate(word): total += column_width(c) if total > space_left: return word[:i - 1], word[i - 1:] return word, ''
def __str__(self): out = [] self.rewrap() def writesep(char="-", lineno=None): # type: (unicode, Optional[int]) -> unicode """Called on the line *before* lineno. Called with no *lineno* for the last sep. """ out = [] # type: List[unicode] for colno, width in enumerate(self.measured_widths): if ( lineno is not None and lineno > 0 and self[lineno, colno] is self[lineno - 1, colno] ): out.append(" " * (width + 2)) else: out.append(char * (width + 2)) head = "+" if out[0][0] == "-" else "|" tail = "+" if out[-1][0] == "-" else "|" glue = [ "+" if left[0] == "-" or right[0] == "-" else "|" for left, right in zip(out, out[1:]) ] glue.append(tail) return head + "".join(chain(*zip(out, glue))) for lineno, line in enumerate(self.lines): if self.separator and lineno == self.separator: out.append(writesep("=", lineno)) else: out.append(writesep("-", lineno)) for physical_line in range(self.physical_lines_for_line(line)): linestr = ["|"] for colno, cell in enumerate(line): if cell.col != colno: continue if lineno != cell.row: physical_text = "" elif physical_line >= len(cell.wrapped): physical_text = "" else: physical_text = cell.wrapped[physical_line] adjust_len = len(physical_text) - column_width(physical_text) linestr.append( " " + physical_text.ljust( self.cell_width(cell, self.measured_widths) + 1 + adjust_len ) + "|" ) out.append("".join(linestr)) out.append(writesep("-")) return "\n".join(out)
def _break_word(word, space_left): """_break_word(word : string, space_left : int) -> (string, string) Break line by unicode width instead of len(word). """ total = 0 for i, c in enumerate(word): total += column_width(c) if total > space_left: return word[:i - 1], word[i - 1:] return word, ''
def depart_title(self, node): if isinstance(node.parent, nodes.section): char = self._title_char else: char = '^' text = ''.join(x[1] for x in self.states.pop() if x[0] == -1) self.stateindent.pop() title = ['', text, '%s' % (char * column_width(text)), ''] if len(self.states) == 2 and len(self.states[-1]) == 0: # remove an empty line before title if it is first section title in the document title.pop(0) self.states[-1].append((0, title))
def rewrap(self): """Call ``cell.wrap()`` on all cells, and measure each column width after wrapping (result written in ``self.measured_widths``). """ self.measured_widths = self.colwidth[:] for cell in self.cells: cell.wrap(width=self.cell_width(cell, self.colwidth)) if not cell.wrapped: continue width = math.ceil(max(column_width(x) for x in cell.wrapped) / cell.colspan) for col in range(cell.col, cell.col + cell.colspan): self.measured_widths[col] = max(self.measured_widths[col], width)
def test_nonascii_title_line(app): title = u'\u65e5\u672c\u8a9e' underline = u'=' * column_width(title) content = u'\n'.join((title, underline, u'')) (app.srcdir / 'contents.rst').write_text(content, encoding='utf-8') app.builder.build_all() result = (app.outdir / 'contents.txt').text(encoding='utf-8') expect_underline = underline.replace('=', '*') result_underline = result.splitlines()[2].strip() assert expect_underline == result_underline
def writerow(row): lines = zip_longest(*row) for line in lines: out = ["|"] for i, cell in enumerate(line): if cell: adjust_len = len(cell) - column_width(cell) out.append(" " + cell.ljust(realwidths[i] + 1 + adjust_len)) else: out.append(" " * (realwidths[i] + 2)) out.append("|") self.add_text("".join(out) + self.nl)
def rewrap(self) -> None: """Call ``cell.wrap()`` on all cells, and measure each column width after wrapping (result written in ``self.measured_widths``). """ self.measured_widths = self.colwidth[:] for cell in self.cells: cell.wrap(width=self.cell_width(cell, self.colwidth)) if not cell.wrapped: continue width = math.ceil(max(column_width(x) for x in cell.wrapped) / cell.colspan) for col in range(cell.col, cell.col + cell.colspan): self.measured_widths[col] = max(self.measured_widths[col], width)
def writerow(row): lines = zip_longest(*row) for line in lines: out = ['|'] for i, cell in enumerate(line): if cell: adjust_len = len(cell) - column_width(cell) out.append(' ' + cell.ljust(realwidths[i] + 1 + adjust_len)) else: out.append(' ' * (realwidths[i] + 2)) out.append('|') self.add_text(''.join(out) + self.nl)
def writerow(row): lines = zip(*row) for line in lines: out = ['|'] for i, cell in enumerate(line): if cell: adjust_len = len(cell) - column_width(cell) out.append(' ' + cell.ljust( realwidths[i] + 1 + adjust_len)) else: out.append(' ' * (realwidths[i] + 2)) out.append('|') self.add_text(''.join(out) + self.nl)
def depart_table(self, node): lines = self.table[1:] fmted_rows = [] colwidths = self.table[0] realwidths = colwidths[:] separator = 0 # don't allow paragraphs in table cells for now for line in lines: if line == "sep": separator = len(fmted_rows) else: cells = [] for i, cell in enumerate(line): par = my_wrap(cell, width=colwidths[i]) if par: maxwidth = max(column_width(x) for x in par) else: maxwidth = 0 realwidths[i] = max(realwidths[i], maxwidth) cells.append(par) fmted_rows.append(cells) def writesep(char="-"): out = ["+"] for width in realwidths: out.append(char * (width + 2)) out.append("+") self.add_text("".join(out) + self.nl) def writerow(row): lines = zip_longest(*row) for line in lines: out = ["|"] for i, cell in enumerate(line): if cell: adjust_len = len(cell) - column_width(cell) out.append(" " + cell.ljust(realwidths[i] + 1 + adjust_len)) else: out.append(" " * (realwidths[i] + 2)) out.append("|") self.add_text("".join(out) + self.nl) for i, row in enumerate(fmted_rows): if separator and i == separator: writesep("=") else: writesep("-") writerow(row) writesep("-") self.table = None self.end_state(wrap=False)
def writerow(row): # Originally written to use *magic lines = list(zip(*row)) for line in lines: out = ['|'] for i, cell in enumerate(line): if cell: adjust_len = len(cell) - column_width(cell) out.append(' ' + cell.ljust(realwidths[i] + 1 + adjust_len)) else: out.append(' ' * (realwidths[i] + 2)) out.append('|') self.add_text(''.join(out) + self.nl)
def depart_title(self, node: Element) -> None: if isinstance(node.parent, nodes.section): char = self._title_char else: char = '^' text = '' text = ''.join(x[1] for x in self.states.pop() if x[0] == -1) # type: ignore if self.add_secnumbers: text = self.get_section_number_string(node) + text self.stateindent.pop() title = ['', text, '%s' % (char * column_width(text)), ''] if len(self.states) == 2 and len(self.states[-1]) == 0: # remove an empty line before title if it is first section title in the document title.pop(0) self.states[-1].append((0, title))
def doctree_resolved(app, doctree, docname): domain_data = app.env.domaindata.setdefault(DOMAIN_NAME, {}) pageinfo = domain_data.setdefault(docname, DEFAULT_PAGEINFO.copy()) for node in doctree.traverse(nodes.Text): text = node.astext() for c in text: if column_width(c) == 1: pageinfo['ascii_count'] += 1 pageinfo['half_char_count'] += 1 pageinfo['full_char_count'] += 0.5 else: pageinfo['nonascii_count'] += 1 pageinfo['half_char_count'] += 2 pageinfo['full_char_count'] += 1 pageinfo['char_count'] += len(text)
def build_header(title, date, author, categories, tags, slug): from docutils.utils import column_width """Build a header from a list of fields""" header = '%s\n%s\n' % (title, '#' * column_width(title)) if date: header += ':date: %s\n' % date if author: header += ':author: %s\n' % author if categories: header += ':category: %s\n' % ', '.join(categories) if tags: header += ':tags: %s\n' % ', '.join(tags) if slug: header += ':slug: %s\n' % slug header += '\n' return header
def depart_title(self, node): # type: (nodes.Node) -> None if isinstance(node.parent, nodes.section): char = self._title_char else: char = '^' text = None # type: unicode text = ''.join(x[1] for x in self.states.pop() if x[0] == -1) # type: ignore if self.add_secnumbers: text = self.get_section_number_string(node) + text self.stateindent.pop() title = ['', text, '%s' % (char * column_width(text)), ''] # type: List[unicode] if len(self.states) == 2 and len(self.states[-1]) == 0: # remove an empty line before title if it is first section title in the document title.pop(0) self.states[-1].append((0, title))
def test_maxwitdh_with_prefix(app, status, warning): app.builder.build_update() result = (app.outdir / 'maxwidth.txt').text(encoding='utf-8') lines = result.splitlines() line_widths = [column_width(line) for line in lines] assert max(line_widths) < MAXWIDTH assert lines[0].startswith('See also: ham') assert lines[1].startswith(' ham') assert lines[2] == '' assert lines[3].startswith('* ham') assert lines[4].startswith(' ham') assert lines[5] == '' assert lines[6].startswith('* ham') assert lines[7].startswith(' ham') assert lines[8] == '' assert lines[9].startswith('spam egg')
def test_nonascii_maxwidth(app): sb_text = u'abc' #length=3 mb_text = u'\u65e5\u672c\u8a9e' #length=3 sb_line = ' '.join([sb_text] * int(MAXWIDTH / 3)) mb_line = ' '.join([mb_text] * int(MAXWIDTH / 3)) mix_line = ' '.join([sb_text, mb_text] * int(MAXWIDTH / 6)) contents = u'\n\n'.join((sb_line, mb_line, mix_line)) (app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8') app.builder.build_all() result = (app.outdir / 'contents.txt').text(encoding='utf-8') lines = [line.strip() for line in result.splitlines() if line.strip()] line_widths = [column_width(line) for line in lines] assert max(line_widths) < MAXWIDTH
def test_nonascii_table(app): text = u'\u65e5\u672c\u8a9e' contents = (u"\n.. list-table::" "\n" "\n - - spam" "\n - egg" "\n" "\n - - %(text)s" "\n - %(text)s" "\n" % locals()) (app.srcdir / 'contents.rst').write_text(contents, encoding='utf-8') app.builder.build_all() result = (app.outdir / 'contents.txt').text(encoding='utf-8') lines = [line.strip() for line in result.splitlines() if line.strip()] line_widths = [column_width(line) for line in lines] assert len(set(line_widths)) == 1 # same widths
def build_header(title, date, author, categories, tags, slug, attachments=None): from docutils.utils import column_width """Build a header from a list of fields""" header = "%s\n%s\n" % (title, "#" * column_width(title)) if date: header += ":date: %s\n" % date if author: header += ":author: %s\n" % author if categories: header += ":category: %s\n" % ", ".join(categories) if tags: header += ":tags: %s\n" % ", ".join(tags) if slug: header += ":slug: %s\n" % slug if attachments: header += ":attachments: %s\n" % ", ".join(attachments) header += "\n" return header
def validate_parenthesis(node): """ If text include half parenthesis within wide text, emit warning. :param docutils.nodes.Node node: node to validate. :return: list of validation error messages :rtype: List[ValidationErrorMessage] """ text = node.astext() msgs = [] for term in find_parethesis(text): if column_width(term) != len(term): old_text = text text = text.replace(u'(%s)' % term, u'(%s)' % term) msg = ValidationErrorMessage( 'Half parenthesis include Wide string', node, old_text, text) msgs.append(msg) return msgs
def validate_question_exclamation(node): """ If text include half question or exclamatoin, emit warning. :param docutils.nodes.Node node: node to validate. :return: list of validation error messages :rtype: List[ValidationErrorMessage] """ text = node.astext() if column_width(text) != len(text): for base, mark in find_question_exclamation(text): wide_mark = mark.replace(u'!', u'!').replace(u'?', u'?') text = text.replace(base + mark, base + wide_mark) msgs = [] if text != node.astext(): msg = ValidationErrorMessage('Half "!", "?" after full-width char', node, node.astext(), text) msgs.append(msg) return msgs
def render(self): """Build a header from a list of fields""" from docutils.utils import column_width header = "%s\n%s\n" % (self.title, "#" * column_width(self.title)) if self.date: header += ":date: %s\n" % self.date if self.author: header += ":author: %s\n" % self.author if self.categories: header += ":category: %s\n" % ", ".join(self.categories) if self.tags: header += ":tags: %s\n" % ", ".join(self.tags) if self.slug: header += ":slug: %s\n" % self.slug if self.status: header += ":status: %s\n" % self.status if self.attachments: header += ":attachments: %s\n" % ", ".join(self.attachments) header += "\n" return header
def test_nonascii_maxwidth(app, status, warning): app.builder.build_update() result = (app.outdir / 'nonascii_maxwidth.txt').text(encoding='utf-8') lines = [line.strip() for line in result.splitlines() if line.strip()] line_widths = [column_width(line) for line in lines] assert max(line_widths) < MAXWIDTH
def generate(d, overwrite=True, silent=False): '''Borrowed from Sphinx 1.3b3''' """Generate project based on values in *d*.""" texescape.init() if 'mastertoctree' not in d: d['mastertoctree'] = '' if 'mastertocmaxdepth' not in d: d['mastertocmaxdepth'] = 2 d['project_fn'] = make_filename(d['project']) d['project_manpage'] = d['project_fn'].lower() d['now'] = time.asctime() d['project_underline'] = column_width(d['project']) * '=' d['copyright'] = time.strftime('%Y') + ', ' + d['author'] d['author_texescaped'] = text_type(d['author'] ).translate(texescape.tex_escape_map) d['project_doc'] = d['project'] + ' Documentation' d['project_doc_texescaped'] = text_type(d['project'] + ' Documentation' ).translate(texescape.tex_escape_map) # escape backslashes and single quotes in strings that are put into # a Python string literal for key in ('project', 'project_doc', 'project_doc_texescaped', 'author', 'author_texescaped', 'copyright', 'version', 'release', 'master'): d[key + '_str'] = d[key].replace('\\', '\\\\').replace("'", "\\'") if not path.isdir(d['path']): mkdir_p(d['path']) srcdir = d['sep'] and path.join(d['path'], 'source') or d['path'] mkdir_p(srcdir) d['exclude_patterns'] = '' #if d['sep']: # builddir = path.join(d['path'], 'build') # #else: # builddir = path.join(srcdir, d['dot'] + 'build') # d['exclude_patterns'] = repr(d['dot'] + 'build') #mkdir_p(builddir) mkdir_p(path.join(srcdir, d['dot'] + 'templates')) mkdir_p(path.join(srcdir, d['dot'] + 'static')) def write_file(fpath, content, newline=None): if overwrite or not path.isfile(fpath): print('Creating file %s.' % fpath) f = open(fpath, 'wt', encoding='utf-8', newline=newline) try: f.write(content) finally: f.close() else: print('File %s already exists, skipping.' % fpath) conf_text = ABLOG_CONF % d write_file(path.join(srcdir, 'conf.py'), conf_text) masterfile = path.join(srcdir, d['master'] + d['suffix']) write_file(masterfile, ABLOG_INDEX % d) about = path.join(srcdir, 'about' + d['suffix']) write_file(about, ABLOG_ABOUT % d) d['post_date'] = datetime.datetime.today().strftime('%b %d, %Y') firstpost = path.join(srcdir, 'first-post' + d['suffix']) write_file(firstpost, ABLOG_POST % d) if silent: return print(bold('Finished: An initial directory structure has been created.'))
def generate(d, overwrite=True, silent=False, templatedir=None): # type: (Dict, bool, bool, str) -> None """Generate project based on values in *d*.""" template = QuickstartRenderer(templatedir=templatedir) texescape.init() if 'mastertoctree' not in d: d['mastertoctree'] = '' if 'mastertocmaxdepth' not in d: d['mastertocmaxdepth'] = 2 d['PY3'] = True d['project_fn'] = make_filename(d['project']) d['project_url'] = quote(d['project'].encode('idna')) d['project_manpage'] = d['project_fn'].lower() d['now'] = time.asctime() d['project_underline'] = column_width(d['project']) * '=' d.setdefault('extensions', []) d['copyright'] = time.strftime('%Y') + ', ' + d['author'] d['author_texescaped'] = text_type(d['author']).\ translate(texescape.tex_escape_map) d['project_doc'] = d['project'] + ' Documentation' d['project_doc_texescaped'] = text_type(d['project'] + ' Documentation').\ translate(texescape.tex_escape_map) # escape backslashes and single quotes in strings that are put into # a Python string literal for key in ('project', 'project_doc', 'project_doc_texescaped', 'author', 'author_texescaped', 'copyright', 'version', 'release', 'master'): d[key + '_str'] = d[key].replace('\\', '\\\\').replace("'", "\\'") ensuredir(d['path']) srcdir = d['sep'] and path.join(d['path'], 'source') or d['path'] ensuredir(srcdir) if d['sep']: builddir = path.join(d['path'], 'build') d['exclude_patterns'] = '' else: builddir = path.join(srcdir, d['dot'] + 'build') exclude_patterns = map(repr, [ d['dot'] + 'build', 'Thumbs.db', '.DS_Store', ]) d['exclude_patterns'] = ', '.join(exclude_patterns) ensuredir(builddir) ensuredir(path.join(srcdir, d['dot'] + 'templates')) ensuredir(path.join(srcdir, d['dot'] + 'static')) def write_file(fpath, content, newline=None): # type: (str, str, str) -> None if overwrite or not path.isfile(fpath): if 'quiet' not in d: print(__('Creating file %s.') % fpath) with open(fpath, 'wt', encoding='utf-8', newline=newline) as f: f.write(content) else: if 'quiet' not in d: print(__('File %s already exists, skipping.') % fpath) conf_path = os.path.join(templatedir, 'conf.py_t') if templatedir else None if not conf_path or not path.isfile(conf_path): conf_path = os.path.join(package_dir, 'templates', 'quickstart', 'conf.py_t') with open(conf_path) as f: conf_text = f.read() write_file(path.join(srcdir, 'conf.py'), template.render_string(conf_text, d)) masterfile = path.join(srcdir, d['master'] + d['suffix']) write_file(masterfile, template.render('quickstart/master_doc.rst_t', d)) if d.get('make_mode') is True: makefile_template = 'quickstart/Makefile.new_t' batchfile_template = 'quickstart/make.bat.new_t' else: makefile_template = 'quickstart/Makefile_t' batchfile_template = 'quickstart/make.bat_t' if d['makefile'] is True: d['rsrcdir'] = d['sep'] and 'source' or '.' d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build' # use binary mode, to avoid writing \r\n on Windows write_file(path.join(d['path'], 'Makefile'), template.render(makefile_template, d), '\n') if d['batchfile'] is True: d['rsrcdir'] = d['sep'] and 'source' or '.' d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build' write_file(path.join(d['path'], 'make.bat'), template.render(batchfile_template, d), '\r\n') if silent: return print() print( bold(__('Finished: An initial directory structure has been created.'))) print( __(''' You should now populate your master file %s and create other documentation source files. ''') % masterfile + ((d['makefile'] or d['batchfile']) and __('''\ Use the Makefile to build the docs, like so: make builder ''') or __('''\ Use the sphinx-build command to build the docs, like so: sphinx-build -b builder %s %s ''') % (srcdir, builddir)) + __('''\ where "builder" is one of the supported builders, e.g. html, latex or linkcheck. '''))
def generate(d, overwrite=True, silent=False, templatedir=None): # type: (Dict, bool, bool, str) -> None """Generate project based on values in *d*.""" template = QuickstartRenderer(templatedir=templatedir) if 'mastertoctree' not in d: d['mastertoctree'] = '' if 'mastertocmaxdepth' not in d: d['mastertocmaxdepth'] = 2 d['now'] = time.asctime() d['project_underline'] = column_width(d['project']) * '=' d.setdefault('extensions', []) d['copyright'] = time.strftime('%Y') + ', ' + d['author'] ensuredir(d['path']) srcdir = d['sep'] and path.join(d['path'], 'source') or d['path'] ensuredir(srcdir) if d['sep']: builddir = path.join(d['path'], 'build') d['exclude_patterns'] = '' else: builddir = path.join(srcdir, d['dot'] + 'build') exclude_patterns = map(repr, [ d['dot'] + 'build', 'Thumbs.db', '.DS_Store', ]) d['exclude_patterns'] = ', '.join(exclude_patterns) ensuredir(builddir) ensuredir(path.join(srcdir, d['dot'] + 'templates')) ensuredir(path.join(srcdir, d['dot'] + 'static')) def write_file(fpath, content, newline=None): # type: (str, str, str) -> None if overwrite or not path.isfile(fpath): if 'quiet' not in d: print(__('Creating file %s.') % fpath) with open(fpath, 'wt', encoding='utf-8', newline=newline) as f: f.write(content) else: if 'quiet' not in d: print(__('File %s already exists, skipping.') % fpath) conf_path = os.path.join(templatedir, 'conf.py_t') if templatedir else None if not conf_path or not path.isfile(conf_path): conf_path = os.path.join(package_dir, 'templates', 'quickstart', 'conf.py_t') with open(conf_path) as f: conf_text = f.read() write_file(path.join(srcdir, 'conf.py'), template.render_string(conf_text, d)) masterfile = path.join(srcdir, d['master'] + d['suffix']) write_file(masterfile, template.render('quickstart/master_doc.rst_t', d)) if d.get('make_mode') is True: makefile_template = 'quickstart/Makefile.new_t' batchfile_template = 'quickstart/make.bat.new_t' else: makefile_template = 'quickstart/Makefile_t' batchfile_template = 'quickstart/make.bat_t' if d['makefile'] is True: d['rsrcdir'] = d['sep'] and 'source' or '.' d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build' # use binary mode, to avoid writing \r\n on Windows write_file(path.join(d['path'], 'Makefile'), template.render(makefile_template, d), '\n') if d['batchfile'] is True: d['rsrcdir'] = d['sep'] and 'source' or '.' d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build' write_file(path.join(d['path'], 'make.bat'), template.render(batchfile_template, d), '\r\n') if silent: return print() print(bold(__('Finished: An initial directory structure has been created.'))) print(__(''' You should now populate your master file %s and create other documentation source files. ''') % masterfile + ((d['makefile'] or d['batchfile']) and __('''\ Use the Makefile to build the docs, like so: make builder ''') or __('''\ Use the sphinx-build command to build the docs, like so: sphinx-build -b builder %s %s ''') % (srcdir, builddir)) + __('''\ where "builder" is one of the supported builders, e.g. html, latex or linkcheck. '''))
def generate(d, overwrite=True, silent=False): """Generate project based on values in *d*.""" texescape.init() indent = ' ' * 4 if 'mastertoctree' not in d: d['mastertoctree'] = '' if 'mastertocmaxdepth' not in d: d['mastertocmaxdepth'] = 2 d['project_fn'] = make_filename(d['project']) d['project_manpage'] = d['project_fn'].lower() d['now'] = time.asctime() d['project_underline'] = column_width(d['project']) * '=' extensions = (',\n' + indent).join( repr('sphinx.ext.' + name) for name in ('autodoc', 'doctest', 'intersphinx', 'todo', 'coverage', 'pngmath', 'mathjax', 'ifconfig', 'viewcode') if d.get('ext_' + name)) if extensions: d['extensions'] = '\n' + indent + extensions + ',\n' else: d['extensions'] = extensions d['copyright'] = time.strftime('%Y') + ', ' + d['author'] d['author_texescaped'] = unicode(d['author']).\ translate(texescape.tex_escape_map) d['project_doc'] = d['project'] + ' Documentation' d['project_doc_texescaped'] = unicode(d['project'] + ' Documentation').\ translate(texescape.tex_escape_map) # escape backslashes and single quotes in strings that are put into # a Python string literal for key in ('project', 'project_doc', 'project_doc_texescaped', 'author', 'author_texescaped', 'copyright', 'version', 'release', 'master'): d[key + '_str'] = d[key].replace('\\', '\\\\').replace("'", "\\'") if not path.isdir(d['path']): mkdir_p(d['path']) srcdir = d['sep'] and path.join(d['path'], 'source') or d['path'] mkdir_p(srcdir) if d['sep']: builddir = path.join(d['path'], 'build') d['exclude_patterns'] = '' else: builddir = path.join(srcdir, d['dot'] + 'build') d['exclude_patterns'] = repr(d['dot'] + 'build') mkdir_p(builddir) mkdir_p(path.join(srcdir, d['dot'] + 'templates')) mkdir_p(path.join(srcdir, d['dot'] + 'static')) def write_file(fpath, content, newline=None): if overwrite or not path.isfile(fpath): print 'Creating file %s.' % fpath f = open(fpath, 'wt', encoding='utf-8', newline=newline) try: f.write(content) finally: f.close() else: print 'File %s already exists, skipping.' % fpath conf_text = QUICKSTART_CONF % d if d['epub']: conf_text += EPUB_CONFIG % d if d.get('ext_intersphinx'): conf_text += INTERSPHINX_CONFIG write_file(path.join(srcdir, 'conf.py'), conf_text) masterfile = path.join(srcdir, d['master'] + d['suffix']) write_file(masterfile, MASTER_FILE % d) if d['makefile']: d['rsrcdir'] = d['sep'] and 'source' or '.' d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build' # use binary mode, to avoid writing \r\n on Windows write_file(path.join(d['path'], 'Makefile'), MAKEFILE % d, u'\n') if d['batchfile']: d['rsrcdir'] = d['sep'] and 'source' or '.' d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build' write_file(path.join(d['path'], 'make.bat'), BATCHFILE % d, u'\r\n') if silent: return print print bold('Finished: An initial directory structure has been created.') print ''' You should now populate your master file %s and create other documentation source files. ''' % masterfile + ((d['makefile'] or d['batchfile']) and '''\ Use the Makefile to build the docs, like so: make builder ''' or '''\ Use the sphinx-build command to build the docs, like so: sphinx-build -b builder %s %s ''' % (srcdir, builddir)) + '''\
def generate(d, overwrite=True, silent=False): """Generate project based on values in *d*.""" template = SphinxRenderer() texescape.init() indent = " " * 4 if "mastertoctree" not in d: d["mastertoctree"] = "" if "mastertocmaxdepth" not in d: d["mastertocmaxdepth"] = 2 d["PY3"] = PY3 d["project_fn"] = make_filename(d["project"]) d["project_url"] = urlquote(d["project"].encode("idna")) d["project_manpage"] = d["project_fn"].lower() d["now"] = time.asctime() d["project_underline"] = column_width(d["project"]) * "=" extensions = (",\n" + indent).join(repr("sphinx.ext." + name) for name in EXTENSIONS if d.get("ext_" + name)) if extensions: d["extensions"] = "\n" + indent + extensions + ",\n" else: d["extensions"] = extensions d["copyright"] = time.strftime("%Y") + ", " + d["author"] d["author_texescaped"] = text_type(d["author"]).translate(texescape.tex_escape_map) d["project_doc"] = d["project"] + " Documentation" d["project_doc_texescaped"] = text_type(d["project"] + " Documentation").translate(texescape.tex_escape_map) # escape backslashes and single quotes in strings that are put into # a Python string literal for key in ( "project", "project_doc", "project_doc_texescaped", "author", "author_texescaped", "copyright", "version", "release", "master", ): d[key + "_str"] = d[key].replace("\\", "\\\\").replace("'", "\\'") if not path.isdir(d["path"]): mkdir_p(d["path"]) srcdir = d["sep"] and path.join(d["path"], "source") or d["path"] mkdir_p(srcdir) if d["sep"]: builddir = path.join(d["path"], "build") d["exclude_patterns"] = "" else: builddir = path.join(srcdir, d["dot"] + "build") exclude_patterns = map(repr, [d["dot"] + "build", "Thumbs.db", ".DS_Store"]) d["exclude_patterns"] = ", ".join(exclude_patterns) mkdir_p(builddir) mkdir_p(path.join(srcdir, d["dot"] + "templates")) mkdir_p(path.join(srcdir, d["dot"] + "static")) def write_file(fpath, content, newline=None): if overwrite or not path.isfile(fpath): print("Creating file %s." % fpath) with open(fpath, "wt", encoding="utf-8", newline=newline) as f: f.write(content) else: print("File %s already exists, skipping." % fpath) with open(os.path.join(package_dir, "templates", "quickstart", "conf.py_t")) as f: conf_text = convert_python_source(f.read()) write_file(path.join(srcdir, "conf.py"), template.render_string(conf_text, d)) masterfile = path.join(srcdir, d["master"] + d["suffix"]) write_file(masterfile, template.render("quickstart/master_doc.rst_t", d)) if d.get("make_mode") is True: makefile_template = "quickstart/Makefile.new_t" batchfile_template = "quickstart/make.bat.new_t" else: makefile_template = "quickstart/Makefile_t" batchfile_template = "quickstart/make.bat_t" if d["makefile"] is True: d["rsrcdir"] = d["sep"] and "source" or "." d["rbuilddir"] = d["sep"] and "build" or d["dot"] + "build" # use binary mode, to avoid writing \r\n on Windows write_file(path.join(d["path"], "Makefile"), template.render(makefile_template, d), u"\n") if d["batchfile"] is True: d["rsrcdir"] = d["sep"] and "source" or "." d["rbuilddir"] = d["sep"] and "build" or d["dot"] + "build" write_file(path.join(d["path"], "make.bat"), template.render(batchfile_template, d), u"\r\n") if silent: return print() print(bold("Finished: An initial directory structure has been created.")) print( """ You should now populate your master file %s and create other documentation source files. """ % masterfile + ( (d["makefile"] or d["batchfile"]) and """\ Use the Makefile to build the docs, like so: make builder """ or """\ Use the sphinx-build command to build the docs, like so: sphinx-build -b builder %s %s """ % (srcdir, builddir) ) + """\ where "builder" is one of the supported builders, e.g. html, latex or linkcheck. """ )
def generate(d, overwrite=True, silent=False): """ Borrowed from Sphinx 1.3b3. Generate project based on values in *d*. """ texescape.init() if "mastertoctree" not in d: d["mastertoctree"] = "" if "mastertocmaxdepth" not in d: d["mastertocmaxdepth"] = 2 d["project_fn"] = make_filename(d["project"]) d["project_manpage"] = d["project_fn"].lower() d["now"] = time.asctime() d["project_underline"] = column_width(d["project"]) * "=" d["copyright"] = time.strftime("%Y") + ", " + d["author"] d["author_texescaped"] = texescape.escape( str(d["author"]).translate(str(d["author"]))) d["project_doc"] = d["project"] + " Documentation" d["project_doc_texescaped"] = texescape.escape( str(d["project"] + " Documentation").translate( str(d["project"] + " Documentation"))) if not path.isdir(d["path"]): ensuredir(d["path"]) srcdir = d["sep"] and path.join(d["path"], "source") or d["path"] ensuredir(srcdir) d["exclude_patterns"] = "" # TODO: Work if we want this. # if d['sep']: # builddir = path.join(d['path'], 'build') # # else: # builddir = path.join(srcdir, d['dot'] + 'build') # d['exclude_patterns'] = repr(d['dot'] + 'build') # ensuredir(builddir) ensuredir(path.join(srcdir, d["dot"] + "templates")) ensuredir(path.join(srcdir, d["dot"] + "static")) def write_file(fpath, content, newline=None): if overwrite or not path.isfile(fpath): print(f"Creating file {fpath}.") f = open(fpath, "wt", encoding="utf-8", newline=newline) try: f.write(content) finally: f.close() else: print(f"File {fpath} already exists, skipping.") conf_text = ABLOG_CONF.format(**d) write_file(path.join(srcdir, "conf.py"), conf_text) masterfile = path.join(srcdir, d["master"] + d["suffix"]) write_file(masterfile, ABLOG_INDEX.format(**d)) about = path.join(srcdir, "about" + d["suffix"]) write_file(about, ABLOG_ABOUT.format(**d)) d["post_date"] = datetime.datetime.today().strftime("%b %d, %Y") firstpost = path.join(srcdir, "first-post" + d["suffix"]) write_file(firstpost, ABLOG_POST.format(**d)) if silent: return print(bold("Finished: An initial directory structure has been created."))
def test_nonascii_table(app, status, warning): app.builder.build_update() result = (app.outdir / 'nonascii_table.txt').text(encoding='utf-8') lines = [line.strip() for line in result.splitlines() if line.strip()] line_widths = [column_width(line) for line in lines] assert len(set(line_widths)) == 1 # same widths
def generate(d, overwrite=True, silent=False, templatedir=None): # type: (Dict, bool, bool, unicode) -> None """Generate project based on values in *d*.""" template = QuickstartRenderer(templatedir=templatedir) texescape.init() indent = ' ' * 4 if 'mastertoctree' not in d: d['mastertoctree'] = '' if 'mastertocmaxdepth' not in d: d['mastertocmaxdepth'] = 2 d['PY3'] = PY3 d['project_fn'] = make_filename(d['project']) d['project_url'] = urlquote(d['project'].encode('idna')) d['project_manpage'] = d['project_fn'].lower() d['now'] = time.asctime() d['project_underline'] = column_width(d['project']) * '=' d.setdefault('extensions', []) for name in EXTENSIONS: if d.get('ext_' + name): d['extensions'].append('sphinx.ext.' + name) d['extensions'] = (',\n' + indent).join(repr(name) for name in d['extensions']) d['copyright'] = time.strftime('%Y') + ', ' + d['author'] d['author_texescaped'] = text_type(d['author']).\ translate(texescape.tex_escape_map) d['project_doc'] = d['project'] + ' Documentation' d['project_doc_texescaped'] = text_type(d['project'] + ' Documentation').\ translate(texescape.tex_escape_map) # escape backslashes and single quotes in strings that are put into # a Python string literal for key in ('project', 'project_doc', 'project_doc_texescaped', 'author', 'author_texescaped', 'copyright', 'version', 'release', 'master'): d[key + '_str'] = d[key].replace('\\', '\\\\').replace("'", "\\'") if not path.isdir(d['path']): ensuredir(d['path']) srcdir = d['sep'] and path.join(d['path'], 'source') or d['path'] ensuredir(srcdir) if d['sep']: builddir = path.join(d['path'], 'build') d['exclude_patterns'] = '' else: builddir = path.join(srcdir, d['dot'] + 'build') exclude_patterns = map(repr, [ d['dot'] + 'build', 'Thumbs.db', '.DS_Store', ]) d['exclude_patterns'] = ', '.join(exclude_patterns) ensuredir(builddir) ensuredir(path.join(srcdir, d['dot'] + 'templates')) ensuredir(path.join(srcdir, d['dot'] + 'static')) def write_file(fpath, content, newline=None): # type: (unicode, unicode, unicode) -> None if overwrite or not path.isfile(fpath): if 'quiet' not in d: print('Creating file %s.' % fpath) with open(fpath, 'wt', encoding='utf-8', newline=newline) as f: f.write(content) else: if 'quiet' not in d: print('File %s already exists, skipping.' % fpath) conf_path = os.path.join(templatedir, 'conf.py_t') if templatedir else None if not conf_path or not path.isfile(conf_path): conf_path = os.path.join(package_dir, 'templates', 'quickstart', 'conf.py_t') with open(conf_path) as f: conf_text = convert_python_source(f.read()) write_file(path.join(srcdir, 'conf.py'), template.render_string(conf_text, d)) masterfile = path.join(srcdir, d['master'] + d['suffix']) write_file(masterfile, template.render('quickstart/master_doc.rst_t', d)) if d.get('make_mode') is True: makefile_template = 'quickstart/Makefile.new_t' batchfile_template = 'quickstart/make.bat.new_t' else: makefile_template = 'quickstart/Makefile_t' batchfile_template = 'quickstart/make.bat_t' if d['makefile'] is True: d['rsrcdir'] = d['sep'] and 'source' or '.' d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build' # use binary mode, to avoid writing \r\n on Windows write_file(path.join(d['path'], 'Makefile'), template.render(makefile_template, d), u'\n') if d['batchfile'] is True: d['rsrcdir'] = d['sep'] and 'source' or '.' d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build' write_file(path.join(d['path'], 'make.bat'), template.render(batchfile_template, d), u'\r\n') if silent: return print() print(bold('Finished: An initial directory structure has been created.')) print(''' You should now populate your master file %s and create other documentation source files. ''' % masterfile + ((d['makefile'] or d['batchfile']) and '''\ Use the Makefile to build the docs, like so: make builder ''' or '''\ Use the sphinx-build command to build the docs, like so: sphinx-build -b builder %s %s ''' % (srcdir, builddir)) + '''\ where "builder" is one of the supported builders, e.g. html, latex or linkcheck. ''')