mercurial/minirst.py
author Martin von Zweigbergk <martinvonz@google.com>
Sat, 09 Mar 2019 22:11:27 -0800
changeset 42409 72522fe7fb95
parent 42251 f9cdd732cb58
child 43076 2372284d9457
permissions -rw-r--r--
merge: reorder some initialization to make more sense This puts the closely related definitions of "pl", "p1", "p2", "pas" close together, and moves the definition of "overwrite" away and closer to where it's first used. Differential Revision: https://phab.mercurial-scm.org/D6471
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
     1
# minirst.py - minimal reStructuredText parser
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
     2
#
10443
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
     3
# Copyright 2009, 2010 Matt Mackall <mpm@selenic.com> and others
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
     4
#
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9741
diff changeset
     6
# GNU General Public License version 2 or any later version.
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
     7
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
     8
"""simplified reStructuredText parser.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
     9
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    10
This parser knows just enough about reStructuredText to parse the
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    11
Mercurial docstrings.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    12
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    13
It cheats in a major way: nested blocks are not really nested. They
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    14
are just indented blocks that look like they are nested. This relies
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    15
on the user to keep the right indentation for the blocks.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    16
26421
4b0fc75f9403 urls: bulk-change primary website URLs
Matt Mackall <mpm@selenic.com>
parents: 26237
diff changeset
    17
Remember to update https://mercurial-scm.org/wiki/HelpStyleGuide
12958
8957c39867f6 minirst: link to HelpStyleGuide in docstring
Martin Geisler <mg@aragost.com>
parents: 12867
diff changeset
    18
when adding support for new constructs.
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    19
"""
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    20
25960
05d97407a8d1 minirst: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25723
diff changeset
    21
from __future__ import absolute_import
12388
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
    22
25960
05d97407a8d1 minirst: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25723
diff changeset
    23
import re
05d97407a8d1 minirst: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25723
diff changeset
    24
05d97407a8d1 minirst: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25723
diff changeset
    25
from .i18n import _
05d97407a8d1 minirst: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25723
diff changeset
    26
from . import (
05d97407a8d1 minirst: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25723
diff changeset
    27
    encoding,
31318
1c3352d7eaf2 minirst: make encoding.encoding unicodes to pass into encode() and decode()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31317
diff changeset
    28
    pycompat,
34695
e178fcaa3933 python3: use our bytes-only version of cgi.escape everywhere
Augie Fackler <augie@google.com>
parents: 34131
diff changeset
    29
    url,
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
    30
)
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
    31
from .utils import (
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
    32
    stringutil,
25960
05d97407a8d1 minirst: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25723
diff changeset
    33
)
18750
c9d923f5d8ae minirst: CGI escape strings prior to embedding it in the HTML
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18749
diff changeset
    34
18748
6e676fb6ea44 help: use a full header for topic titles
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 17424
diff changeset
    35
def section(s):
6e676fb6ea44 help: use a full header for topic titles
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 17424
diff changeset
    36
    return "%s\n%s\n\n" % (s, "\"" * encoding.colwidth(s))
6e676fb6ea44 help: use a full header for topic titles
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 17424
diff changeset
    37
6e676fb6ea44 help: use a full header for topic titles
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 17424
diff changeset
    38
def subsection(s):
6e676fb6ea44 help: use a full header for topic titles
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 17424
diff changeset
    39
    return "%s\n%s\n\n" % (s, '=' * encoding.colwidth(s))
6e676fb6ea44 help: use a full header for topic titles
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 17424
diff changeset
    40
6e676fb6ea44 help: use a full header for topic titles
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 17424
diff changeset
    41
def subsubsection(s):
6e676fb6ea44 help: use a full header for topic titles
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 17424
diff changeset
    42
    return "%s\n%s\n\n" % (s, "-" * encoding.colwidth(s))
6e676fb6ea44 help: use a full header for topic titles
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 17424
diff changeset
    43
6e676fb6ea44 help: use a full header for topic titles
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 17424
diff changeset
    44
def subsubsubsection(s):
6e676fb6ea44 help: use a full header for topic titles
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 17424
diff changeset
    45
    return "%s\n%s\n\n" % (s, "." * encoding.colwidth(s))
6e676fb6ea44 help: use a full header for topic titles
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 17424
diff changeset
    46
42251
f9cdd732cb58 minirst: support subsubsubsubsections (header level 5) with marker ''''
Sietse Brouwer <sbbrouwer@gmail.com>
parents: 41759
diff changeset
    47
def subsubsubsubsection(s):
f9cdd732cb58 minirst: support subsubsubsubsections (header level 5) with marker ''''
Sietse Brouwer <sbbrouwer@gmail.com>
parents: 41759
diff changeset
    48
    return "%s\n%s\n\n" % (s, "'" * encoding.colwidth(s))
f9cdd732cb58 minirst: support subsubsubsubsections (header level 5) with marker ''''
Sietse Brouwer <sbbrouwer@gmail.com>
parents: 41759
diff changeset
    49
11464
521c8e0c93bf minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11297
diff changeset
    50
def replace(text, substs):
15393
87bb6b7644f6 minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15262
diff changeset
    51
    '''
87bb6b7644f6 minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15262
diff changeset
    52
    Apply a list of (find, replace) pairs to a text.
87bb6b7644f6 minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15262
diff changeset
    53
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 32526
diff changeset
    54
    >>> replace(b"foo bar", [(b'f', b'F'), (b'b', b'B')])
15393
87bb6b7644f6 minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15262
diff changeset
    55
    'Foo Bar'
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 32526
diff changeset
    56
    >>> encoding.encoding = b'latin1'
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 32526
diff changeset
    57
    >>> replace(b'\\x81\\\\', [(b'\\\\', b'/')])
15393
87bb6b7644f6 minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15262
diff changeset
    58
    '\\x81/'
34131
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 32526
diff changeset
    59
    >>> encoding.encoding = b'shiftjis'
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 32526
diff changeset
    60
    >>> replace(b'\\x81\\\\', [(b'\\\\', b'/')])
15393
87bb6b7644f6 minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15262
diff changeset
    61
    '\\x81\\\\'
87bb6b7644f6 minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15262
diff changeset
    62
    '''
87bb6b7644f6 minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15262
diff changeset
    63
87bb6b7644f6 minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15262
diff changeset
    64
    # some character encodings (cp932 for Japanese, at least) use
87bb6b7644f6 minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15262
diff changeset
    65
    # ASCII characters other than control/alphabet/digit as a part of
87bb6b7644f6 minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15262
diff changeset
    66
    # multi-bytes characters, so direct replacing with such characters
87bb6b7644f6 minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15262
diff changeset
    67
    # on strings in local encoding causes invalid byte sequences.
31318
1c3352d7eaf2 minirst: make encoding.encoding unicodes to pass into encode() and decode()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31317
diff changeset
    68
    utext = text.decode(pycompat.sysstr(encoding.encoding))
11464
521c8e0c93bf minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11297
diff changeset
    69
    for f, t in substs:
21745
4c62478be2ea minirst: explicitly decode substitutions
Matt Mackall <mpm@selenic.com>
parents: 20682
diff changeset
    70
        utext = utext.replace(f.decode("ascii"), t.decode("ascii"))
31318
1c3352d7eaf2 minirst: make encoding.encoding unicodes to pass into encode() and decode()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31317
diff changeset
    71
    return utext.encode(pycompat.sysstr(encoding.encoding))
12651
17f28de168a4 minirst: refactor/simplify findblocks
Martin Geisler <mg@lazybytes.net>
parents: 12620
diff changeset
    72
31317
0bd32d7c9002 minirst: make regular expressions bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31132
diff changeset
    73
_blockre = re.compile(br"\n(?:\s*\n)+")
12651
17f28de168a4 minirst: refactor/simplify findblocks
Martin Geisler <mg@lazybytes.net>
parents: 12620
diff changeset
    74
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    75
def findblocks(text):
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    76
    """Find continuous blocks of lines in text.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    77
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    78
    Returns a list of dictionaries representing the blocks. Each block
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    79
    has an 'indent' field and a 'lines' field.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    80
    """
12651
17f28de168a4 minirst: refactor/simplify findblocks
Martin Geisler <mg@lazybytes.net>
parents: 12620
diff changeset
    81
    blocks = []
15036
bb96e12a3242 minirst: only strip leading newlines, not indentation
Matt Mackall <mpm@selenic.com>
parents: 15015
diff changeset
    82
    for b in _blockre.split(text.lstrip('\n').rstrip()):
12651
17f28de168a4 minirst: refactor/simplify findblocks
Martin Geisler <mg@lazybytes.net>
parents: 12620
diff changeset
    83
        lines = b.splitlines()
15123
9b41ccb2043e minirst: don't choke on empty text
Matt Mackall <mpm@selenic.com>
parents: 15122
diff changeset
    84
        if lines:
9b41ccb2043e minirst: don't choke on empty text
Matt Mackall <mpm@selenic.com>
parents: 15122
diff changeset
    85
            indent = min((len(l) - len(l.lstrip())) for l in lines)
9b41ccb2043e minirst: don't choke on empty text
Matt Mackall <mpm@selenic.com>
parents: 15122
diff changeset
    86
            lines = [l[indent:] for l in lines]
20682
7f8cbaaa8eea minirst: move from dict() construction to {} literals
Augie Fackler <raf@durin42.com>
parents: 20654
diff changeset
    87
            blocks.append({'indent': indent, 'lines': lines})
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    88
    return blocks
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    89
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    90
def findliteralblocks(blocks):
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    91
    """Finds literal blocks and adds a 'type' field to the blocks.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    92
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    93
    Literal blocks are given the type 'literal', all other blocks are
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    94
    given type the 'paragraph'.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    95
    """
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    96
    i = 0
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    97
    while i < len(blocks):
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    98
        # Searching for a block that looks like this:
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    99
        #
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   100
        # +------------------------------+
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   101
        # | paragraph                    |
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   102
        # | (ends with "::")             |
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   103
        # +------------------------------+
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   104
        #    +---------------------------+
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   105
        #    | indented literal block    |
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   106
        #    +---------------------------+
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   107
        blocks[i]['type'] = 'paragraph'
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   108
        if blocks[i]['lines'][-1].endswith('::') and i + 1 < len(blocks):
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   109
            indent = blocks[i]['indent']
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   110
            adjustment = blocks[i + 1]['indent'] - indent
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   111
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   112
            if blocks[i]['lines'] == ['::']:
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   113
                # Expanded form: remove block
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   114
                del blocks[i]
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   115
                i -= 1
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   116
            elif blocks[i]['lines'][-1].endswith(' ::'):
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   117
                # Partially minimized form: remove space and both
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   118
                # colons.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   119
                blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-3]
41759
aaad36b88298 cleanup: use () to wrap long lines instead of \
Augie Fackler <augie@google.com>
parents: 41365
diff changeset
   120
            elif (len(blocks[i]['lines']) == 1 and
aaad36b88298 cleanup: use () to wrap long lines instead of \
Augie Fackler <augie@google.com>
parents: 41365
diff changeset
   121
                  blocks[i]['lines'][0].lstrip(' ').startswith('.. ') and
aaad36b88298 cleanup: use () to wrap long lines instead of \
Augie Fackler <augie@google.com>
parents: 41365
diff changeset
   122
                  blocks[i]['lines'][0].find(' ', 3) == -1):
20549
2025315cfb0c comments: fix minor spelling issues found with spell checker
Mads Kiilerich <madski@unity3d.com>
parents: 19995
diff changeset
   123
                # directive on its own line, not a literal block
19992
8ac7b85bd8f9 minirst: do not interpret a directive as a literal block
Simon Heimberg <simohe@besonet.ch>
parents: 18752
diff changeset
   124
                i += 1
8ac7b85bd8f9 minirst: do not interpret a directive as a literal block
Simon Heimberg <simohe@besonet.ch>
parents: 18752
diff changeset
   125
                continue
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   126
            else:
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   127
                # Fully minimized form: remove just one colon.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   128
                blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-1]
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   129
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   130
            # List items are formatted with a hanging indent. We must
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   131
            # correct for this here while we still have the original
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   132
            # information on the indentation of the subsequent literal
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   133
            # blocks available.
9738
f52c4f7a4732 minirst: prepare for general types of bullet lists
Martin Geisler <mg@lazybytes.net>
parents: 9737
diff changeset
   134
            m = _bulletre.match(blocks[i]['lines'][0])
f52c4f7a4732 minirst: prepare for general types of bullet lists
Martin Geisler <mg@lazybytes.net>
parents: 9737
diff changeset
   135
            if m:
f52c4f7a4732 minirst: prepare for general types of bullet lists
Martin Geisler <mg@lazybytes.net>
parents: 9737
diff changeset
   136
                indent += m.end()
f52c4f7a4732 minirst: prepare for general types of bullet lists
Martin Geisler <mg@lazybytes.net>
parents: 9737
diff changeset
   137
                adjustment -= m.end()
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   138
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   139
            # Mark the following indented blocks.
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   140
            while i + 1 < len(blocks) and blocks[i + 1]['indent'] > indent:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   141
                blocks[i + 1]['type'] = 'literal'
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   142
                blocks[i + 1]['indent'] -= adjustment
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   143
                i += 1
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   144
        i += 1
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   145
    return blocks
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   146
31317
0bd32d7c9002 minirst: make regular expressions bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31132
diff changeset
   147
_bulletre = re.compile(br'(\*|-|[0-9A-Za-z]+\.|\(?[0-9A-Za-z]+\)|\|) ')
0bd32d7c9002 minirst: make regular expressions bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31132
diff changeset
   148
_optionre = re.compile(br'^(-([a-zA-Z0-9]), )?(--[a-z0-9-]+)'
0bd32d7c9002 minirst: make regular expressions bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31132
diff changeset
   149
                       br'((.*)  +)(.*)$')
0bd32d7c9002 minirst: make regular expressions bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31132
diff changeset
   150
_fieldre = re.compile(br':(?![: ])([^:]*)(?<! ):[ ]+(.*)')
0bd32d7c9002 minirst: make regular expressions bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31132
diff changeset
   151
_definitionre = re.compile(br'[^ ]')
0bd32d7c9002 minirst: make regular expressions bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31132
diff changeset
   152
_tablere = re.compile(br'(=+\s+)*=+')
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   153
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   154
def splitparagraphs(blocks):
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   155
    """Split paragraphs into lists."""
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   156
    # Tuples with (list type, item regexp, single line items?). Order
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   157
    # matters: definition lists has the least specific regexp and must
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   158
    # come last.
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   159
    listtypes = [('bullet', _bulletre, True),
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   160
                 ('option', _optionre, True),
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   161
                 ('field', _fieldre, True),
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   162
                 ('definition', _definitionre, False)]
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   163
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   164
    def match(lines, i, itemre, singleline):
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   165
        """Does itemre match an item at line i?
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   166
17424
e7cfe3587ea4 fix trivial spelling errors
Mads Kiilerich <mads@kiilerich.com>
parents: 16815
diff changeset
   167
        A list item can be followed by an indented line or another list
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   168
        item (but only if singleline is True).
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   169
        """
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   170
        line1 = lines[i]
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   171
        line2 = i + 1 < len(lines) and lines[i + 1] or ''
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   172
        if not itemre.match(line1):
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   173
            return False
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   174
        if singleline:
37883
a61583cba509 minirst: fix bytes slicing defect on Python 3
Augie Fackler <augie@google.com>
parents: 37084
diff changeset
   175
            return line2 == '' or line2[0:1] == ' ' or itemre.match(line2)
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   176
        else:
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   177
            return line2.startswith(' ')
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   178
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   179
    i = 0
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   180
    while i < len(blocks):
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   181
        if blocks[i]['type'] == 'paragraph':
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   182
            lines = blocks[i]['lines']
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   183
            for type, itemre, singleline in listtypes:
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   184
                if match(lines, 0, itemre, singleline):
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   185
                    items = []
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   186
                    for j, line in enumerate(lines):
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   187
                        if match(lines, j, itemre, singleline):
20682
7f8cbaaa8eea minirst: move from dict() construction to {} literals
Augie Fackler <raf@durin42.com>
parents: 20654
diff changeset
   188
                            items.append({'type': type, 'lines': [],
7f8cbaaa8eea minirst: move from dict() construction to {} literals
Augie Fackler <raf@durin42.com>
parents: 20654
diff changeset
   189
                                          'indent': blocks[i]['indent']})
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   190
                        items[-1]['lines'].append(line)
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   191
                    blocks[i:i + 1] = items
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   192
                    break
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   193
        i += 1
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   194
    return blocks
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   195
15861
ee8f5e4ce7b8 minirst: simplify and standardize field list formatting
Olav Reinert <seroton10@gmail.com>
parents: 15393
diff changeset
   196
_fieldwidth = 14
10065
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   197
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   198
def updatefieldlists(blocks):
15861
ee8f5e4ce7b8 minirst: simplify and standardize field list formatting
Olav Reinert <seroton10@gmail.com>
parents: 15393
diff changeset
   199
    """Find key for field lists."""
10065
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   200
    i = 0
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   201
    while i < len(blocks):
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   202
        if blocks[i]['type'] != 'field':
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   203
            i += 1
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   204
            continue
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   205
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   206
        j = i
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   207
        while j < len(blocks) and blocks[j]['type'] == 'field':
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   208
            m = _fieldre.match(blocks[j]['lines'][0])
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   209
            key, rest = m.groups()
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   210
            blocks[j]['lines'][0] = rest
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   211
            blocks[j]['key'] = key
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   212
            j += 1
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   213
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   214
        i = j + 1
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   215
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   216
    return blocks
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   217
13011
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   218
def updateoptionlists(blocks):
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   219
    i = 0
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   220
    while i < len(blocks):
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   221
        if blocks[i]['type'] != 'option':
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   222
            i += 1
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   223
            continue
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   224
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   225
        optstrwidth = 0
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   226
        j = i
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   227
        while j < len(blocks) and blocks[j]['type'] == 'option':
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   228
            m = _optionre.match(blocks[j]['lines'][0])
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   229
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   230
            shortoption = m.group(2)
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   231
            group3 = m.group(3)
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   232
            longoption = group3[2:].strip()
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   233
            desc = m.group(6).strip()
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   234
            longoptionarg = m.group(5).strip()
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   235
            blocks[j]['lines'][0] = desc
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   236
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   237
            noshortop = ''
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   238
            if not shortoption:
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   239
                noshortop = '   '
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   240
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   241
            opt = "%s%s" %   (shortoption and "-%s " % shortoption or '',
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   242
                            ("%s--%s %s") % (noshortop, longoption,
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   243
                                             longoptionarg))
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   244
            opt = opt.rstrip()
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   245
            blocks[j]['optstr'] = opt
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   246
            optstrwidth = max(optstrwidth, encoding.colwidth(opt))
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   247
            j += 1
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   248
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   249
        for block in blocks[i:j]:
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   250
            block['optstrwidth'] = optstrwidth
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   251
        i = j + 1
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   252
    return blocks
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   253
10443
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   254
def prunecontainers(blocks, keep):
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   255
    """Prune unwanted containers.
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   256
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   257
    The blocks must have a 'type' field, i.e., they should have been
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   258
    run through findliteralblocks first.
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   259
    """
10444
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   260
    pruned = []
10443
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   261
    i = 0
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   262
    while i + 1 < len(blocks):
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   263
        # Searching for a block that looks like this:
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   264
        #
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   265
        # +-------+---------------------------+
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   266
        # | ".. container ::" type            |
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   267
        # +---+                               |
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   268
        #     | blocks                        |
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   269
        #     +-------------------------------+
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   270
        if (blocks[i]['type'] == 'paragraph' and
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   271
            blocks[i]['lines'][0].startswith('.. container::')):
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   272
            indent = blocks[i]['indent']
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   273
            adjustment = blocks[i + 1]['indent'] - indent
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   274
            containertype = blocks[i]['lines'][0][15:]
22584
19bd8bda6bb2 minirst: allow multiple container types for prune
Matt Mackall <mpm@selenic.com>
parents: 21745
diff changeset
   275
            prune = True
19bd8bda6bb2 minirst: allow multiple container types for prune
Matt Mackall <mpm@selenic.com>
parents: 21745
diff changeset
   276
            for c in keep:
19bd8bda6bb2 minirst: allow multiple container types for prune
Matt Mackall <mpm@selenic.com>
parents: 21745
diff changeset
   277
                if c in containertype.split('.'):
19bd8bda6bb2 minirst: allow multiple container types for prune
Matt Mackall <mpm@selenic.com>
parents: 21745
diff changeset
   278
                    prune = False
10444
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   279
            if prune:
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   280
                pruned.append(containertype)
10443
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   281
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   282
            # Always delete "..container:: type" block
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   283
            del blocks[i]
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   284
            j = i
15102
a7e375d087f6 minirst: fix container stripping logic
Matt Mackall <mpm@selenic.com>
parents: 15039
diff changeset
   285
            i -= 1
10443
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   286
            while j < len(blocks) and blocks[j]['indent'] > indent:
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   287
                if prune:
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   288
                    del blocks[j]
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   289
                else:
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   290
                    blocks[j]['indent'] -= adjustment
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   291
                    j += 1
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   292
        i += 1
10444
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   293
    return blocks, pruned
10443
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   294
31317
0bd32d7c9002 minirst: make regular expressions bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31132
diff changeset
   295
_sectionre = re.compile(br"""^([-=`:.'"~^_*+#])\1+$""")
10984
68b7d2d668ce minirst: support all recommended title adornments
Martin Geisler <mg@lazybytes.net>
parents: 10983
diff changeset
   296
15037
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   297
def findtables(blocks):
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   298
    '''Find simple tables
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   299
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   300
       Only simple one-line table elements are supported
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   301
    '''
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   302
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   303
    for block in blocks:
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   304
        # Searching for a block that looks like this:
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   305
        #
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   306
        # === ==== ===
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   307
        #  A    B   C
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   308
        # === ==== ===  <- optional
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   309
        #  1    2   3
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   310
        #  x    y   z
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   311
        # === ==== ===
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   312
        if (block['type'] == 'paragraph' and
15192
3834ca04664a rst: fix detection of single-row tables
Matt Mackall <mpm@selenic.com>
parents: 15145
diff changeset
   313
            len(block['lines']) > 2 and
15037
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   314
            _tablere.match(block['lines'][0]) and
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   315
            block['lines'][0] == block['lines'][-1]):
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   316
            block['type'] = 'table'
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   317
            block['header'] = False
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   318
            div = block['lines'][0]
15144
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   319
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   320
            # column markers are ASCII so we can calculate column
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   321
            # position in bytes
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37883
diff changeset
   322
            columns = [x for x in pycompat.xrange(len(div))
32526
9d08283946f0 minirst: look for column delimiters using slices instead of indicies
Augie Fackler <raf@durin42.com>
parents: 32525
diff changeset
   323
                       if div[x:x + 1] == '=' and (x == 0 or
9d08283946f0 minirst: look for column delimiters using slices instead of indicies
Augie Fackler <raf@durin42.com>
parents: 32525
diff changeset
   324
                                                   div[x - 1:x] == ' ')]
15037
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   325
            rows = []
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   326
            for l in block['lines'][1:-1]:
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   327
                if l == div:
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   328
                    block['header'] = True
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   329
                    continue
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   330
                row = []
15144
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   331
                # we measure columns not in bytes or characters but in
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   332
                # colwidth which makes things tricky
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   333
                pos = columns[0] # leading whitespace is bytes
15037
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   334
                for n, start in enumerate(columns):
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   335
                    if n + 1 < len(columns):
15144
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   336
                        width = columns[n + 1] - start
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   337
                        v = encoding.getcols(l, pos, width) # gather columns
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   338
                        pos += len(v) # calculate byte position of end
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   339
                        row.append(v.strip())
15037
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   340
                    else:
15144
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   341
                        row.append(l[pos:].strip())
15037
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   342
                rows.append(row)
15144
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   343
15037
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   344
            block['table'] = rows
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   345
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   346
    return blocks
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   347
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   348
def findsections(blocks):
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   349
    """Finds sections.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   350
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   351
    The blocks must have a 'type' field, i.e., they should have been
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   352
    run through findliteralblocks first.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   353
    """
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   354
    for block in blocks:
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   355
        # Searching for a block that looks like this:
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   356
        #
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   357
        # +------------------------------+
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   358
        # | Section title                |
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   359
        # | -------------                |
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   360
        # +------------------------------+
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   361
        if (block['type'] == 'paragraph' and
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   362
            len(block['lines']) == 2 and
12867
eda77c3e246a minirst: use colwidth to match title lengths (issue2455)
Matt Mackall <mpm@selenic.com>
parents: 12819
diff changeset
   363
            encoding.colwidth(block['lines'][0]) == len(block['lines'][1]) and
10984
68b7d2d668ce minirst: support all recommended title adornments
Martin Geisler <mg@lazybytes.net>
parents: 10983
diff changeset
   364
            _sectionre.match(block['lines'][1])):
32525
043c147c928d minirst: grab a byte, not an int, for the underline style
Augie Fackler <raf@durin42.com>
parents: 32524
diff changeset
   365
            block['underline'] = block['lines'][1][0:1]
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   366
            block['type'] = 'section'
10983
287a5cdf7743 minirst: correctly format sections containing inline markup
Martin Geisler <mg@lazybytes.net>
parents: 10972
diff changeset
   367
            del block['lines'][1]
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   368
    return blocks
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   369
9623
32727ce029de minirst: convert ``foo`` into "foo" upon display
Martin Geisler <mg@lazybytes.net>
parents: 9540
diff changeset
   370
def inlineliterals(blocks):
11464
521c8e0c93bf minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11297
diff changeset
   371
    substs = [('``', '"')]
9623
32727ce029de minirst: convert ``foo`` into "foo" upon display
Martin Geisler <mg@lazybytes.net>
parents: 9540
diff changeset
   372
    for b in blocks:
10983
287a5cdf7743 minirst: correctly format sections containing inline markup
Martin Geisler <mg@lazybytes.net>
parents: 10972
diff changeset
   373
        if b['type'] in ('paragraph', 'section'):
11464
521c8e0c93bf minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11297
diff changeset
   374
            b['lines'] = [replace(l, substs) for l in b['lines']]
9623
32727ce029de minirst: convert ``foo`` into "foo" upon display
Martin Geisler <mg@lazybytes.net>
parents: 9540
diff changeset
   375
    return blocks
32727ce029de minirst: convert ``foo`` into "foo" upon display
Martin Geisler <mg@lazybytes.net>
parents: 9540
diff changeset
   376
10972
0a2c6948f5f4 doc, minirst: support hg interpreted text role
Martin Geisler <mg@aragost.com>
parents: 10937
diff changeset
   377
def hgrole(blocks):
27729
58f8b29c37ff minirst: change hgrole to use single quotes
timeless <timeless@mozdev.org>
parents: 27614
diff changeset
   378
    substs = [(':hg:`', "'hg "), ('`', "'")]
10972
0a2c6948f5f4 doc, minirst: support hg interpreted text role
Martin Geisler <mg@aragost.com>
parents: 10937
diff changeset
   379
    for b in blocks:
10983
287a5cdf7743 minirst: correctly format sections containing inline markup
Martin Geisler <mg@lazybytes.net>
parents: 10972
diff changeset
   380
        if b['type'] in ('paragraph', 'section'):
11192
babf9a5f5528 minirst: handle line breaks in hg role
Martin Geisler <mg@aragost.com>
parents: 11189
diff changeset
   381
            # Turn :hg:`command` into "hg command". This also works
babf9a5f5528 minirst: handle line breaks in hg role
Martin Geisler <mg@aragost.com>
parents: 11189
diff changeset
   382
            # when there is a line break in the command and relies on
babf9a5f5528 minirst: handle line breaks in hg role
Martin Geisler <mg@aragost.com>
parents: 11189
diff changeset
   383
            # the fact that we have no stray back-quotes in the input
babf9a5f5528 minirst: handle line breaks in hg role
Martin Geisler <mg@aragost.com>
parents: 11189
diff changeset
   384
            # (run the blocks through inlineliterals first).
11464
521c8e0c93bf minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11297
diff changeset
   385
            b['lines'] = [replace(l, substs) for l in b['lines']]
10972
0a2c6948f5f4 doc, minirst: support hg interpreted text role
Martin Geisler <mg@aragost.com>
parents: 10937
diff changeset
   386
    return blocks
0a2c6948f5f4 doc, minirst: support hg interpreted text role
Martin Geisler <mg@aragost.com>
parents: 10937
diff changeset
   387
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   388
def addmargins(blocks):
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   389
    """Adds empty blocks for vertical spacing.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   390
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   391
    This groups bullets, options, and definitions together with no vertical
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   392
    space between them, and adds an empty block between all other blocks.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   393
    """
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   394
    i = 1
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   395
    while i < len(blocks):
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   396
        if (blocks[i]['type'] == blocks[i - 1]['type'] and
10936
2853c891ac41 minirst: add margin around definition items
Martin Geisler <mg@lazybytes.net>
parents: 10447
diff changeset
   397
            blocks[i]['type'] in ('bullet', 'option', 'field')):
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   398
            i += 1
19995
0f6e360b14f2 minirst: do not add a 2nd empty paragraph
Simon Heimberg <simohe@besonet.ch>
parents: 19994
diff changeset
   399
        elif not blocks[i - 1]['lines']:
20549
2025315cfb0c comments: fix minor spelling issues found with spell checker
Mads Kiilerich <madski@unity3d.com>
parents: 19995
diff changeset
   400
            # no lines in previous block, do not separate
19995
0f6e360b14f2 minirst: do not add a 2nd empty paragraph
Simon Heimberg <simohe@besonet.ch>
parents: 19994
diff changeset
   401
            i += 1
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   402
        else:
20682
7f8cbaaa8eea minirst: move from dict() construction to {} literals
Augie Fackler <raf@durin42.com>
parents: 20654
diff changeset
   403
            blocks.insert(i, {'lines': [''], 'indent': 0, 'type': 'margin'})
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   404
            i += 2
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   405
    return blocks
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   406
12819
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   407
def prunecomments(blocks):
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   408
    """Remove comments."""
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   409
    i = 0
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   410
    while i < len(blocks):
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   411
        b = blocks[i]
13009
54be08fa4d1d minirst: modified minirst to also recognize empty comments.
Erik Zielke <ez@aragost.com>
parents: 13003
diff changeset
   412
        if b['type'] == 'paragraph' and (b['lines'][0].startswith('.. ') or
54be08fa4d1d minirst: modified minirst to also recognize empty comments.
Erik Zielke <ez@aragost.com>
parents: 13003
diff changeset
   413
                                         b['lines'] == ['..']):
12819
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   414
            del blocks[i]
13003
876a931dd230 minirst: better interaction between comments and margins
Martin Geisler <mg@aragost.com>
parents: 12958
diff changeset
   415
            if i < len(blocks) and blocks[i]['type'] == 'margin':
876a931dd230 minirst: better interaction between comments and margins
Martin Geisler <mg@aragost.com>
parents: 12958
diff changeset
   416
                del blocks[i]
12819
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   417
        else:
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   418
            i += 1
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   419
    return blocks
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   420
31131
50a49ead4db4 minirst: dynamically compile admonitions regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31130
diff changeset
   421
31132
bbdd712e9adb minirst: support passing admonitions into findadmonitions() and parse()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31131
diff changeset
   422
def findadmonitions(blocks, admonitions=None):
12388
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   423
    """
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   424
    Makes the type of the block an admonition block if
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   425
    the first line is an admonition directive
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   426
    """
31714
bbf7a29dcf9b minirst: remove redundant _admonitions set
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31713
diff changeset
   427
    admonitions = admonitions or _admonitiontitles.keys()
31132
bbdd712e9adb minirst: support passing admonitions into findadmonitions() and parse()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31131
diff changeset
   428
31317
0bd32d7c9002 minirst: make regular expressions bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31132
diff changeset
   429
    admonitionre = re.compile(br'\.\. (%s)::' % '|'.join(sorted(admonitions)),
31131
50a49ead4db4 minirst: dynamically compile admonitions regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31130
diff changeset
   430
                              flags=re.IGNORECASE)
50a49ead4db4 minirst: dynamically compile admonitions regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31130
diff changeset
   431
12388
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   432
    i = 0
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   433
    while i < len(blocks):
31131
50a49ead4db4 minirst: dynamically compile admonitions regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31130
diff changeset
   434
        m = admonitionre.match(blocks[i]['lines'][0])
12388
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   435
        if m:
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   436
            blocks[i]['type'] = 'admonition'
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   437
            admonitiontitle = blocks[i]['lines'][0][3:m.end() - 2].lower()
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   438
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   439
            firstline = blocks[i]['lines'][0][m.end() + 1:]
12620
9a9312e84e4e minirst: small code cleanup
Martin Geisler <mg@lazybytes.net>
parents: 12388
diff changeset
   440
            if firstline:
9a9312e84e4e minirst: small code cleanup
Martin Geisler <mg@lazybytes.net>
parents: 12388
diff changeset
   441
                blocks[i]['lines'].insert(1, '   ' + firstline)
12388
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   442
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   443
            blocks[i]['admonitiontitle'] = admonitiontitle
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   444
            del blocks[i]['lines'][0]
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   445
        i = i + 1
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   446
    return blocks
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   447
31712
b3640334a43a minirst: reindent _admonitiontitles
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31340
diff changeset
   448
_admonitiontitles = {
b3640334a43a minirst: reindent _admonitiontitles
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31340
diff changeset
   449
    'attention': _('Attention:'),
b3640334a43a minirst: reindent _admonitiontitles
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31340
diff changeset
   450
    'caution': _('Caution:'),
b3640334a43a minirst: reindent _admonitiontitles
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31340
diff changeset
   451
    'danger': _('!Danger!'),
b3640334a43a minirst: reindent _admonitiontitles
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31340
diff changeset
   452
    'error': _('Error:'),
b3640334a43a minirst: reindent _admonitiontitles
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31340
diff changeset
   453
    'hint': _('Hint:'),
b3640334a43a minirst: reindent _admonitiontitles
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31340
diff changeset
   454
    'important': _('Important:'),
b3640334a43a minirst: reindent _admonitiontitles
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31340
diff changeset
   455
    'note': _('Note:'),
b3640334a43a minirst: reindent _admonitiontitles
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31340
diff changeset
   456
    'tip': _('Tip:'),
b3640334a43a minirst: reindent _admonitiontitles
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31340
diff changeset
   457
    'warning': _('Warning!'),
b3640334a43a minirst: reindent _admonitiontitles
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31340
diff changeset
   458
}
12652
3c31c0e42b11 minirst: pull admonition titles out formatblock function
Martin Geisler <mg@lazybytes.net>
parents: 12651
diff changeset
   459
13011
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   460
def formatoption(block, width):
32524
6e9a2c9c1f37 minirst: use bytes.strip instead of str.strip
Augie Fackler <raf@durin42.com>
parents: 31714
diff changeset
   461
    desc = ' '.join(map(bytes.strip, block['lines']))
13011
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   462
    colwidth = encoding.colwidth(block['optstr'])
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   463
    usablewidth = width - 1
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   464
    hanging = block['optstrwidth']
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   465
    initindent = '%s%s  ' % (block['optstr'], ' ' * ((hanging - colwidth)))
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   466
    hangindent = ' ' * (encoding.colwidth(initindent) + 1)
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   467
    return ' %s\n' % (stringutil.wrap(desc, usablewidth,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   468
                                      initindent=initindent,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   469
                                      hangindent=hangindent))
13011
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   470
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   471
def formatblock(block, width):
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   472
    """Format a block according to width."""
9417
4c3fb45123e5 util, minirst: do not crash with COLUMNS=0
Martin Geisler <mg@lazybytes.net>
parents: 9293
diff changeset
   473
    if width <= 0:
4c3fb45123e5 util, minirst: do not crash with COLUMNS=0
Martin Geisler <mg@lazybytes.net>
parents: 9293
diff changeset
   474
        width = 78
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   475
    indent = ' ' * block['indent']
12388
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   476
    if block['type'] == 'admonition':
12652
3c31c0e42b11 minirst: pull admonition titles out formatblock function
Martin Geisler <mg@lazybytes.net>
parents: 12651
diff changeset
   477
        admonition = _admonitiontitles[block['admonitiontitle']]
19993
03ec85b9cfc4 minirst: do not fail on an empty admonition block
Simon Heimberg <simohe@besonet.ch>
parents: 19992
diff changeset
   478
        if not block['lines']:
03ec85b9cfc4 minirst: do not fail on an empty admonition block
Simon Heimberg <simohe@besonet.ch>
parents: 19992
diff changeset
   479
            return indent + admonition + '\n'
12388
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   480
        hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   481
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   482
        defindent = indent + hang * ' '
32524
6e9a2c9c1f37 minirst: use bytes.strip instead of str.strip
Augie Fackler <raf@durin42.com>
parents: 31714
diff changeset
   483
        text = ' '.join(map(bytes.strip, block['lines']))
15125
bdc595059108 minirst: end all blocks with newlines
Matt Mackall <mpm@selenic.com>
parents: 15123
diff changeset
   484
        return '%s\n%s\n' % (indent + admonition,
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   485
                             stringutil.wrap(text, width=width,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   486
                                             initindent=defindent,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   487
                                             hangindent=defindent))
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   488
    if block['type'] == 'margin':
15125
bdc595059108 minirst: end all blocks with newlines
Matt Mackall <mpm@selenic.com>
parents: 15123
diff changeset
   489
        return '\n'
9735
97d0d910fa5d minirst: remove unnecessary "elif:" statements
Martin Geisler <mg@lazybytes.net>
parents: 9623
diff changeset
   490
    if block['type'] == 'literal':
9291
cd5b6a11b607 minirst: indent literal blocks with two spaces
Martin Geisler <mg@lazybytes.net>
parents: 9156
diff changeset
   491
        indent += '  '
15125
bdc595059108 minirst: end all blocks with newlines
Matt Mackall <mpm@selenic.com>
parents: 15123
diff changeset
   492
        return indent + ('\n' + indent).join(block['lines']) + '\n'
9735
97d0d910fa5d minirst: remove unnecessary "elif:" statements
Martin Geisler <mg@lazybytes.net>
parents: 9623
diff changeset
   493
    if block['type'] == 'section':
12867
eda77c3e246a minirst: use colwidth to match title lengths (issue2455)
Matt Mackall <mpm@selenic.com>
parents: 12819
diff changeset
   494
        underline = encoding.colwidth(block['lines'][0]) * block['underline']
15125
bdc595059108 minirst: end all blocks with newlines
Matt Mackall <mpm@selenic.com>
parents: 15123
diff changeset
   495
        return "%s%s\n%s%s\n" % (indent, block['lines'][0],indent, underline)
15037
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   496
    if block['type'] == 'table':
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   497
        table = block['table']
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   498
        # compute column widths
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   499
        widths = [max([encoding.colwidth(e) for e in c]) for c in zip(*table)]
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   500
        text = ''
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   501
        span = sum(widths) + len(widths) - 1
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   502
        indent = ' ' * block['indent']
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   503
        hang = ' ' * (len(indent) + span - widths[-1])
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   504
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   505
        for row in table:
15144
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   506
            l = []
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   507
            for w, v in zip(widths, row):
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   508
                pad = ' ' * (w - encoding.colwidth(v))
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   509
                l.append(v + pad)
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   510
            l = ' '.join(l)
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   511
            l = stringutil.wrap(l, width=width,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   512
                                initindent=indent,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   513
                                hangindent=hang)
15037
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   514
            if not text and block['header']:
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   515
                text = l + '\n' + indent + '-' * (min(width, span)) + '\n'
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   516
            else:
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   517
                text += l + "\n"
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   518
        return text
9735
97d0d910fa5d minirst: remove unnecessary "elif:" statements
Martin Geisler <mg@lazybytes.net>
parents: 9623
diff changeset
   519
    if block['type'] == 'definition':
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   520
        term = indent + block['lines'][0]
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   521
        hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   522
        defindent = indent + hang * ' '
32524
6e9a2c9c1f37 minirst: use bytes.strip instead of str.strip
Augie Fackler <raf@durin42.com>
parents: 31714
diff changeset
   523
        text = ' '.join(map(bytes.strip, block['lines'][1:]))
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   524
        return '%s\n%s\n' % (term, stringutil.wrap(text, width=width,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   525
                                                   initindent=defindent,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   526
                                                   hangindent=defindent))
10937
a9d5943d2a30 minirst: removed unnecessary initindent variable
Martin Geisler <mg@lazybytes.net>
parents: 10936
diff changeset
   527
    subindent = indent
9735
97d0d910fa5d minirst: remove unnecessary "elif:" statements
Martin Geisler <mg@lazybytes.net>
parents: 9623
diff changeset
   528
    if block['type'] == 'bullet':
10447
e957cc7cbd14 minirst: support line blocks
Martin Geisler <mg@lazybytes.net>
parents: 10444
diff changeset
   529
        if block['lines'][0].startswith('| '):
e957cc7cbd14 minirst: support line blocks
Martin Geisler <mg@lazybytes.net>
parents: 10444
diff changeset
   530
            # Remove bullet for line blocks and add no extra
26781
1aee2ab0f902 spelling: trivial spell checking
Mads Kiilerich <madski@unity3d.com>
parents: 26421
diff changeset
   531
            # indentation.
10447
e957cc7cbd14 minirst: support line blocks
Martin Geisler <mg@lazybytes.net>
parents: 10444
diff changeset
   532
            block['lines'][0] = block['lines'][0][2:]
e957cc7cbd14 minirst: support line blocks
Martin Geisler <mg@lazybytes.net>
parents: 10444
diff changeset
   533
        else:
e957cc7cbd14 minirst: support line blocks
Martin Geisler <mg@lazybytes.net>
parents: 10444
diff changeset
   534
            m = _bulletre.match(block['lines'][0])
e957cc7cbd14 minirst: support line blocks
Martin Geisler <mg@lazybytes.net>
parents: 10444
diff changeset
   535
            subindent = indent + m.end() * ' '
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   536
    elif block['type'] == 'field':
10065
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   537
        key = block['key']
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   538
        subindent = indent + _fieldwidth * ' '
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   539
        if len(key) + 2 > _fieldwidth:
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   540
            # key too large, use full line width
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   541
            key = key.ljust(width)
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   542
        else:
15861
ee8f5e4ce7b8 minirst: simplify and standardize field list formatting
Olav Reinert <seroton10@gmail.com>
parents: 15393
diff changeset
   543
            # key fits within field width
10065
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   544
            key = key.ljust(_fieldwidth)
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   545
        block['lines'][0] = key + block['lines'][0]
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   546
    elif block['type'] == 'option':
13011
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   547
        return formatoption(block, width)
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   548
31340
ff25b89a0776 minirst: use bytes.strip instead of str.strip
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31318
diff changeset
   549
    text = ' '.join(map(bytes.strip, block['lines']))
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   550
    return stringutil.wrap(text, width=width,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   551
                           initindent=indent,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34695
diff changeset
   552
                           hangindent=subindent) + '\n'
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   553
15261
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   554
def formathtml(blocks):
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   555
    """Format RST blocks as HTML"""
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   556
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   557
    out = []
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   558
    headernest = ''
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   559
    listnest = []
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   560
18750
c9d923f5d8ae minirst: CGI escape strings prior to embedding it in the HTML
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18749
diff changeset
   561
    def escape(s):
34695
e178fcaa3933 python3: use our bytes-only version of cgi.escape everywhere
Augie Fackler <augie@google.com>
parents: 34131
diff changeset
   562
        return url.escape(s, True)
18750
c9d923f5d8ae minirst: CGI escape strings prior to embedding it in the HTML
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18749
diff changeset
   563
15261
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   564
    def openlist(start, level):
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   565
        if not listnest or listnest[-1][0] != start:
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   566
            listnest.append((start, level))
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   567
            out.append('<%s>\n' % start)
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   568
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   569
    blocks = [b for b in blocks if b['type'] != 'margin']
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   570
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   571
    for pos, b in enumerate(blocks):
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   572
        btype = b['type']
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   573
        level = b['indent']
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   574
        lines = b['lines']
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   575
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   576
        if btype == 'admonition':
18750
c9d923f5d8ae minirst: CGI escape strings prior to embedding it in the HTML
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18749
diff changeset
   577
            admonition = escape(_admonitiontitles[b['admonitiontitle']])
32524
6e9a2c9c1f37 minirst: use bytes.strip instead of str.strip
Augie Fackler <raf@durin42.com>
parents: 31714
diff changeset
   578
            text = escape(' '.join(map(bytes.strip, lines)))
15261
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   579
            out.append('<p>\n<b>%s</b> %s\n</p>\n' % (admonition, text))
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   580
        elif btype == 'paragraph':
18750
c9d923f5d8ae minirst: CGI escape strings prior to embedding it in the HTML
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18749
diff changeset
   581
            out.append('<p>\n%s\n</p>\n' % escape('\n'.join(lines)))
15261
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   582
        elif btype == 'margin':
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   583
            pass
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   584
        elif btype == 'literal':
18750
c9d923f5d8ae minirst: CGI escape strings prior to embedding it in the HTML
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18749
diff changeset
   585
            out.append('<pre>\n%s\n</pre>\n' % escape('\n'.join(lines)))
15261
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   586
        elif btype == 'section':
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   587
            i = b['underline']
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   588
            if i not in headernest:
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   589
                headernest += i
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   590
            level = headernest.index(i) + 1
18750
c9d923f5d8ae minirst: CGI escape strings prior to embedding it in the HTML
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18749
diff changeset
   591
            out.append('<h%d>%s</h%d>\n' % (level, escape(lines[0]), level))
15261
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   592
        elif btype == 'table':
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   593
            table = b['table']
18752
fabbaa250977 minirst: optimize HTML table generation a bit
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18751
diff changeset
   594
            out.append('<table>\n')
15261
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   595
            for row in table:
18752
fabbaa250977 minirst: optimize HTML table generation a bit
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18751
diff changeset
   596
                out.append('<tr>')
18750
c9d923f5d8ae minirst: CGI escape strings prior to embedding it in the HTML
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18749
diff changeset
   597
                for v in row:
18752
fabbaa250977 minirst: optimize HTML table generation a bit
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18751
diff changeset
   598
                    out.append('<td>')
fabbaa250977 minirst: optimize HTML table generation a bit
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18751
diff changeset
   599
                    out.append(escape(v))
fabbaa250977 minirst: optimize HTML table generation a bit
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18751
diff changeset
   600
                    out.append('</td>')
fabbaa250977 minirst: optimize HTML table generation a bit
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18751
diff changeset
   601
                    out.append('\n')
fabbaa250977 minirst: optimize HTML table generation a bit
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18751
diff changeset
   602
                out.pop()
fabbaa250977 minirst: optimize HTML table generation a bit
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18751
diff changeset
   603
                out.append('</tr>\n')
fabbaa250977 minirst: optimize HTML table generation a bit
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18751
diff changeset
   604
            out.append('</table>\n')
15261
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   605
        elif btype == 'definition':
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   606
            openlist('dl', level)
18750
c9d923f5d8ae minirst: CGI escape strings prior to embedding it in the HTML
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18749
diff changeset
   607
            term = escape(lines[0])
32524
6e9a2c9c1f37 minirst: use bytes.strip instead of str.strip
Augie Fackler <raf@durin42.com>
parents: 31714
diff changeset
   608
            text = escape(' '.join(map(bytes.strip, lines[1:])))
15261
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   609
            out.append(' <dt>%s\n <dd>%s\n' % (term, text))
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   610
        elif btype == 'bullet':
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   611
            bullet, head = lines[0].split(' ', 1)
31130
6582b3716ae0 minirst: detect bullet lists using asterisks
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30390
diff changeset
   612
            if bullet in ('*', '-'):
15261
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   613
                openlist('ul', level)
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   614
            else:
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   615
                openlist('ol', level)
18750
c9d923f5d8ae minirst: CGI escape strings prior to embedding it in the HTML
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18749
diff changeset
   616
            out.append(' <li> %s\n' % escape(' '.join([head] + lines[1:])))
15261
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   617
        elif btype == 'field':
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   618
            openlist('dl', level)
18750
c9d923f5d8ae minirst: CGI escape strings prior to embedding it in the HTML
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18749
diff changeset
   619
            key = escape(b['key'])
32524
6e9a2c9c1f37 minirst: use bytes.strip instead of str.strip
Augie Fackler <raf@durin42.com>
parents: 31714
diff changeset
   620
            text = escape(' '.join(map(bytes.strip, lines)))
15261
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   621
            out.append(' <dt>%s\n <dd>%s\n' % (key, text))
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   622
        elif btype == 'option':
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   623
            openlist('dl', level)
18750
c9d923f5d8ae minirst: CGI escape strings prior to embedding it in the HTML
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 18749
diff changeset
   624
            opt = escape(b['optstr'])
32524
6e9a2c9c1f37 minirst: use bytes.strip instead of str.strip
Augie Fackler <raf@durin42.com>
parents: 31714
diff changeset
   625
            desc = escape(' '.join(map(bytes.strip, lines)))
15261
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   626
            out.append(' <dt>%s\n <dd>%s\n' % (opt, desc))
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   627
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   628
        # close lists if indent level of next block is lower
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   629
        if listnest:
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   630
            start, level = listnest[-1]
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   631
            if pos == len(blocks) - 1:
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   632
                out.append('</%s>\n' % start)
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   633
                listnest.pop()
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   634
            else:
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   635
                nb = blocks[pos + 1]
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   636
                ni = nb['indent']
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   637
                if (ni < level or
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   638
                    (ni == level and
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   639
                     nb['type'] not in 'definition bullet field option')):
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   640
                    out.append('</%s>\n' % start)
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   641
                    listnest.pop()
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   642
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   643
    return ''.join(out)
e2df5b866d22 minirst: add basic HTML formatting support
Matt Mackall <mpm@selenic.com>
parents: 15192
diff changeset
   644
31132
bbdd712e9adb minirst: support passing admonitions into findadmonitions() and parse()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31131
diff changeset
   645
def parse(text, indent=0, keep=None, admonitions=None):
15012
ee766af457ed minirst: add parse method to get document structure
Matt Mackall <mpm@selenic.com>
parents: 14433
diff changeset
   646
    """Parse text into a list of blocks"""
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   647
    blocks = findblocks(text)
9540
cad36e496640 help: un-indent help topics
Martin Geisler <mg@lazybytes.net>
parents: 9417
diff changeset
   648
    for b in blocks:
cad36e496640 help: un-indent help topics
Martin Geisler <mg@lazybytes.net>
parents: 9417
diff changeset
   649
        b['indent'] += indent
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   650
    blocks = findliteralblocks(blocks)
15037
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   651
    blocks = findtables(blocks)
10444
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   652
    blocks, pruned = prunecontainers(blocks, keep or [])
10983
287a5cdf7743 minirst: correctly format sections containing inline markup
Martin Geisler <mg@lazybytes.net>
parents: 10972
diff changeset
   653
    blocks = findsections(blocks)
9623
32727ce029de minirst: convert ``foo`` into "foo" upon display
Martin Geisler <mg@lazybytes.net>
parents: 9540
diff changeset
   654
    blocks = inlineliterals(blocks)
10972
0a2c6948f5f4 doc, minirst: support hg interpreted text role
Martin Geisler <mg@aragost.com>
parents: 10937
diff changeset
   655
    blocks = hgrole(blocks)
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   656
    blocks = splitparagraphs(blocks)
10065
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   657
    blocks = updatefieldlists(blocks)
13011
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   658
    blocks = updateoptionlists(blocks)
31132
bbdd712e9adb minirst: support passing admonitions into findadmonitions() and parse()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31131
diff changeset
   659
    blocks = findadmonitions(blocks, admonitions=admonitions)
13003
876a931dd230 minirst: better interaction between comments and margins
Martin Geisler <mg@aragost.com>
parents: 12958
diff changeset
   660
    blocks = addmargins(blocks)
12819
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   661
    blocks = prunecomments(blocks)
15012
ee766af457ed minirst: add parse method to get document structure
Matt Mackall <mpm@selenic.com>
parents: 14433
diff changeset
   662
    return blocks, pruned
ee766af457ed minirst: add parse method to get document structure
Matt Mackall <mpm@selenic.com>
parents: 14433
diff changeset
   663
15013
4a1e3c761ec7 minirst: add formatblocks helper
Matt Mackall <mpm@selenic.com>
parents: 15012
diff changeset
   664
def formatblocks(blocks, width):
15125
bdc595059108 minirst: end all blocks with newlines
Matt Mackall <mpm@selenic.com>
parents: 15123
diff changeset
   665
    text = ''.join(formatblock(b, width) for b in blocks)
15013
4a1e3c761ec7 minirst: add formatblocks helper
Matt Mackall <mpm@selenic.com>
parents: 15012
diff changeset
   666
    return text
4a1e3c761ec7 minirst: add formatblocks helper
Matt Mackall <mpm@selenic.com>
parents: 15012
diff changeset
   667
39307
92e9aa38a578 minirst: extract function that formats parsed blocks as plain text
Yuya Nishihara <yuya@tcha.org>
parents: 39306
diff changeset
   668
def formatplain(blocks, width):
92e9aa38a578 minirst: extract function that formats parsed blocks as plain text
Yuya Nishihara <yuya@tcha.org>
parents: 39306
diff changeset
   669
    """Format parsed blocks as plain text"""
92e9aa38a578 minirst: extract function that formats parsed blocks as plain text
Yuya Nishihara <yuya@tcha.org>
parents: 39306
diff changeset
   670
    return ''.join(formatblock(b, width) for b in blocks)
92e9aa38a578 minirst: extract function that formats parsed blocks as plain text
Yuya Nishihara <yuya@tcha.org>
parents: 39306
diff changeset
   671
22587
c3c3dd31fe1c help: basic support for showing only specified topic sections
Matt Mackall <mpm@selenic.com>
parents: 22584
diff changeset
   672
def format(text, width=80, indent=0, keep=None, style='plain', section=None):
15012
ee766af457ed minirst: add parse method to get document structure
Matt Mackall <mpm@selenic.com>
parents: 14433
diff changeset
   673
    """Parse and format the text according to width."""
ee766af457ed minirst: add parse method to get document structure
Matt Mackall <mpm@selenic.com>
parents: 14433
diff changeset
   674
    blocks, pruned = parse(text, indent, keep or [])
39305
200ad3e85a97 minirst: extract function that filters parsed blocks by section name
Yuya Nishihara <yuya@tcha.org>
parents: 38783
diff changeset
   675
    if section:
200ad3e85a97 minirst: extract function that filters parsed blocks by section name
Yuya Nishihara <yuya@tcha.org>
parents: 38783
diff changeset
   676
        blocks = filtersections(blocks, section)
200ad3e85a97 minirst: extract function that filters parsed blocks by section name
Yuya Nishihara <yuya@tcha.org>
parents: 38783
diff changeset
   677
    if style == 'html':
39310
a2a5d4ad5276 minirst: make format() simply return a formatted text
Yuya Nishihara <yuya@tcha.org>
parents: 39307
diff changeset
   678
        return formathtml(blocks)
39305
200ad3e85a97 minirst: extract function that filters parsed blocks by section name
Yuya Nishihara <yuya@tcha.org>
parents: 38783
diff changeset
   679
    else:
39310
a2a5d4ad5276 minirst: make format() simply return a formatted text
Yuya Nishihara <yuya@tcha.org>
parents: 39307
diff changeset
   680
        return formatplain(blocks, width=width)
39305
200ad3e85a97 minirst: extract function that filters parsed blocks by section name
Yuya Nishihara <yuya@tcha.org>
parents: 38783
diff changeset
   681
200ad3e85a97 minirst: extract function that filters parsed blocks by section name
Yuya Nishihara <yuya@tcha.org>
parents: 38783
diff changeset
   682
def filtersections(blocks, section):
39341
ca2f4dabf51d minirst: filter blocks by full path to section
Yuya Nishihara <yuya@tcha.org>
parents: 39340
diff changeset
   683
    """Select parsed blocks under the specified section
ca2f4dabf51d minirst: filter blocks by full path to section
Yuya Nishihara <yuya@tcha.org>
parents: 39340
diff changeset
   684
ca2f4dabf51d minirst: filter blocks by full path to section
Yuya Nishihara <yuya@tcha.org>
parents: 39340
diff changeset
   685
    The section name is separated by a dot, and matches the suffix of the
ca2f4dabf51d minirst: filter blocks by full path to section
Yuya Nishihara <yuya@tcha.org>
parents: 39340
diff changeset
   686
    full section path.
ca2f4dabf51d minirst: filter blocks by full path to section
Yuya Nishihara <yuya@tcha.org>
parents: 39340
diff changeset
   687
    """
26113
9b70eda7529c help: distinguish sections when multiple match (issue4802)
timeless@mozdev.org
parents: 25960
diff changeset
   688
    parents = []
39340
b2feccc199c2 minirst: mark getsections() as an internal helper
Yuya Nishihara <yuya@tcha.org>
parents: 39311
diff changeset
   689
    sections = _getsections(blocks)
39306
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   690
    blocks = []
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   691
    i = 0
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   692
    lastparents = []
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   693
    synthetic = []
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   694
    collapse = True
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   695
    while i < len(sections):
39341
ca2f4dabf51d minirst: filter blocks by full path to section
Yuya Nishihara <yuya@tcha.org>
parents: 39340
diff changeset
   696
        path, nest, b = sections[i]
39306
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   697
        del parents[nest:]
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   698
        parents.append(i)
39341
ca2f4dabf51d minirst: filter blocks by full path to section
Yuya Nishihara <yuya@tcha.org>
parents: 39340
diff changeset
   699
        if path == section or path.endswith('.' + section):
39306
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   700
            if lastparents != parents:
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   701
                llen = len(lastparents)
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   702
                plen = len(parents)
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   703
                if llen and llen != plen:
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   704
                    collapse = False
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   705
                s = []
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   706
                for j in pycompat.xrange(3, plen - 1):
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   707
                    parent = parents[j]
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   708
                    if (j >= llen or
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   709
                        lastparents[j] != parent):
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   710
                        s.append(len(blocks))
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   711
                        sec = sections[parent][2]
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   712
                        blocks.append(sec[0])
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   713
                        blocks.append(sec[-1])
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   714
                if s:
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   715
                    synthetic.append(s)
27614
1d7e824ad093 help: include section heading if section depth changes
timeless <timeless@mozdev.org>
parents: 26781
diff changeset
   716
39306
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   717
            lastparents = parents[:]
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   718
            blocks.extend(b)
22770
de9424647fe4 help: show all nested subsections of a section with `hg help foo.section`
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22769
diff changeset
   719
39306
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   720
            ## Also show all subnested sections
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   721
            while i + 1 < len(sections) and sections[i + 1][1] > nest:
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   722
                i += 1
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   723
                blocks.extend(sections[i][2])
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   724
        i += 1
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   725
    if collapse:
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   726
        synthetic.reverse()
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   727
        for s in synthetic:
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   728
            path = [blocks[syn]['lines'][0] for syn in s]
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   729
            real = s[-1] + 2
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   730
            realline = blocks[real]['lines']
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   731
            realline[0] = ('"%s"' %
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   732
                           '.'.join(path + [realline[0]]).replace('"', ''))
9fe97e676250 minirst: unindent "if True" block in filtersections()
Yuya Nishihara <yuya@tcha.org>
parents: 39305
diff changeset
   733
            del blocks[s[0]:real]
22770
de9424647fe4 help: show all nested subsections of a section with `hg help foo.section`
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22769
diff changeset
   734
39305
200ad3e85a97 minirst: extract function that filters parsed blocks by section name
Yuya Nishihara <yuya@tcha.org>
parents: 38783
diff changeset
   735
    return blocks
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   736
39340
b2feccc199c2 minirst: mark getsections() as an internal helper
Yuya Nishihara <yuya@tcha.org>
parents: 39311
diff changeset
   737
def _getsections(blocks):
39341
ca2f4dabf51d minirst: filter blocks by full path to section
Yuya Nishihara <yuya@tcha.org>
parents: 39340
diff changeset
   738
    '''return a list of (section path, nesting level, blocks) tuples'''
15014
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   739
    nest = ""
39341
ca2f4dabf51d minirst: filter blocks by full path to section
Yuya Nishihara <yuya@tcha.org>
parents: 39340
diff changeset
   740
    names = ()
15014
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   741
    secs = []
22587
c3c3dd31fe1c help: basic support for showing only specified topic sections
Matt Mackall <mpm@selenic.com>
parents: 22584
diff changeset
   742
c3c3dd31fe1c help: basic support for showing only specified topic sections
Matt Mackall <mpm@selenic.com>
parents: 22584
diff changeset
   743
    def getname(b):
25723
2a8d8b4097c8 help: support 'hg help template.somekeyword'
Matt Harbison <matt_harbison@yahoo.com>
parents: 22770
diff changeset
   744
        if b['type'] == 'field':
2a8d8b4097c8 help: support 'hg help template.somekeyword'
Matt Harbison <matt_harbison@yahoo.com>
parents: 22770
diff changeset
   745
            x = b['key']
2a8d8b4097c8 help: support 'hg help template.somekeyword'
Matt Harbison <matt_harbison@yahoo.com>
parents: 22770
diff changeset
   746
        else:
2a8d8b4097c8 help: support 'hg help template.somekeyword'
Matt Harbison <matt_harbison@yahoo.com>
parents: 22770
diff changeset
   747
            x = b['lines'][0]
29155
aaabed77791a help: search section of help topic by translated section name correctly
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 27729
diff changeset
   748
        x = encoding.lower(x).strip('"')
22587
c3c3dd31fe1c help: basic support for showing only specified topic sections
Matt Mackall <mpm@selenic.com>
parents: 22584
diff changeset
   749
        if '(' in x:
c3c3dd31fe1c help: basic support for showing only specified topic sections
Matt Mackall <mpm@selenic.com>
parents: 22584
diff changeset
   750
            x = x.split('(')[0]
c3c3dd31fe1c help: basic support for showing only specified topic sections
Matt Mackall <mpm@selenic.com>
parents: 22584
diff changeset
   751
        return x
c3c3dd31fe1c help: basic support for showing only specified topic sections
Matt Mackall <mpm@selenic.com>
parents: 22584
diff changeset
   752
15014
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   753
    for b in blocks:
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   754
        if b['type'] == 'section':
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   755
            i = b['underline']
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   756
            if i not in nest:
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   757
                nest += i
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   758
            level = nest.index(i) + 1
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   759
            nest = nest[:level]
39341
ca2f4dabf51d minirst: filter blocks by full path to section
Yuya Nishihara <yuya@tcha.org>
parents: 39340
diff changeset
   760
            names = names[:level] + (getname(b),)
ca2f4dabf51d minirst: filter blocks by full path to section
Yuya Nishihara <yuya@tcha.org>
parents: 39340
diff changeset
   761
            secs.append(('.'.join(names), level, [b]))
25723
2a8d8b4097c8 help: support 'hg help template.somekeyword'
Matt Harbison <matt_harbison@yahoo.com>
parents: 22770
diff changeset
   762
        elif b['type'] in ('definition', 'field'):
22587
c3c3dd31fe1c help: basic support for showing only specified topic sections
Matt Mackall <mpm@selenic.com>
parents: 22584
diff changeset
   763
            i = ' '
c3c3dd31fe1c help: basic support for showing only specified topic sections
Matt Mackall <mpm@selenic.com>
parents: 22584
diff changeset
   764
            if i not in nest:
c3c3dd31fe1c help: basic support for showing only specified topic sections
Matt Mackall <mpm@selenic.com>
parents: 22584
diff changeset
   765
                nest += i
c3c3dd31fe1c help: basic support for showing only specified topic sections
Matt Mackall <mpm@selenic.com>
parents: 22584
diff changeset
   766
            level = nest.index(i) + 1
c3c3dd31fe1c help: basic support for showing only specified topic sections
Matt Mackall <mpm@selenic.com>
parents: 22584
diff changeset
   767
            nest = nest[:level]
26237
1c6f7cc52da9 minirst: establish leveling for nested definitions
timeless@mozdev.org
parents: 26170
diff changeset
   768
            for i in range(1, len(secs) + 1):
1c6f7cc52da9 minirst: establish leveling for nested definitions
timeless@mozdev.org
parents: 26170
diff changeset
   769
                sec = secs[-i]
1c6f7cc52da9 minirst: establish leveling for nested definitions
timeless@mozdev.org
parents: 26170
diff changeset
   770
                if sec[1] < level:
1c6f7cc52da9 minirst: establish leveling for nested definitions
timeless@mozdev.org
parents: 26170
diff changeset
   771
                    break
1c6f7cc52da9 minirst: establish leveling for nested definitions
timeless@mozdev.org
parents: 26170
diff changeset
   772
                siblings = [a for a in sec[2] if a['type'] == 'definition']
1c6f7cc52da9 minirst: establish leveling for nested definitions
timeless@mozdev.org
parents: 26170
diff changeset
   773
                if siblings:
1c6f7cc52da9 minirst: establish leveling for nested definitions
timeless@mozdev.org
parents: 26170
diff changeset
   774
                    siblingindent = siblings[-1]['indent']
1c6f7cc52da9 minirst: establish leveling for nested definitions
timeless@mozdev.org
parents: 26170
diff changeset
   775
                    indent = b['indent']
1c6f7cc52da9 minirst: establish leveling for nested definitions
timeless@mozdev.org
parents: 26170
diff changeset
   776
                    if siblingindent < indent:
1c6f7cc52da9 minirst: establish leveling for nested definitions
timeless@mozdev.org
parents: 26170
diff changeset
   777
                        level += 1
1c6f7cc52da9 minirst: establish leveling for nested definitions
timeless@mozdev.org
parents: 26170
diff changeset
   778
                        break
1c6f7cc52da9 minirst: establish leveling for nested definitions
timeless@mozdev.org
parents: 26170
diff changeset
   779
                    elif siblingindent == indent:
1c6f7cc52da9 minirst: establish leveling for nested definitions
timeless@mozdev.org
parents: 26170
diff changeset
   780
                        level = sec[1]
1c6f7cc52da9 minirst: establish leveling for nested definitions
timeless@mozdev.org
parents: 26170
diff changeset
   781
                        break
39341
ca2f4dabf51d minirst: filter blocks by full path to section
Yuya Nishihara <yuya@tcha.org>
parents: 39340
diff changeset
   782
            names = names[:level] + (getname(b),)
ca2f4dabf51d minirst: filter blocks by full path to section
Yuya Nishihara <yuya@tcha.org>
parents: 39340
diff changeset
   783
            secs.append(('.'.join(names), level, [b]))
15014
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   784
        else:
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   785
            if not secs:
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   786
                # add an initial empty section
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   787
                secs = [('', 0, [])]
26157
65e41f388970 minirst: don't treat top level item as children of last item (issue4803)
timeless@mozdev.org
parents: 26113
diff changeset
   788
            if b['type'] != 'margin':
65e41f388970 minirst: don't treat top level item as children of last item (issue4803)
timeless@mozdev.org
parents: 26113
diff changeset
   789
                pointer = 1
65e41f388970 minirst: don't treat top level item as children of last item (issue4803)
timeless@mozdev.org
parents: 26113
diff changeset
   790
                bindent = b['indent']
65e41f388970 minirst: don't treat top level item as children of last item (issue4803)
timeless@mozdev.org
parents: 26113
diff changeset
   791
                while pointer < len(secs):
65e41f388970 minirst: don't treat top level item as children of last item (issue4803)
timeless@mozdev.org
parents: 26113
diff changeset
   792
                    section = secs[-pointer][2][0]
65e41f388970 minirst: don't treat top level item as children of last item (issue4803)
timeless@mozdev.org
parents: 26113
diff changeset
   793
                    if section['type'] != 'margin':
65e41f388970 minirst: don't treat top level item as children of last item (issue4803)
timeless@mozdev.org
parents: 26113
diff changeset
   794
                        sindent = section['indent']
65e41f388970 minirst: don't treat top level item as children of last item (issue4803)
timeless@mozdev.org
parents: 26113
diff changeset
   795
                        if len(section['lines']) > 1:
41759
aaad36b88298 cleanup: use () to wrap long lines instead of \
Augie Fackler <augie@google.com>
parents: 41365
diff changeset
   796
                            sindent += (len(section['lines'][1]) -
aaad36b88298 cleanup: use () to wrap long lines instead of \
Augie Fackler <augie@google.com>
parents: 41365
diff changeset
   797
                                        len(section['lines'][1].lstrip(' ')))
26157
65e41f388970 minirst: don't treat top level item as children of last item (issue4803)
timeless@mozdev.org
parents: 26113
diff changeset
   798
                        if bindent >= sindent:
65e41f388970 minirst: don't treat top level item as children of last item (issue4803)
timeless@mozdev.org
parents: 26113
diff changeset
   799
                            break
65e41f388970 minirst: don't treat top level item as children of last item (issue4803)
timeless@mozdev.org
parents: 26113
diff changeset
   800
                    pointer += 1
65e41f388970 minirst: don't treat top level item as children of last item (issue4803)
timeless@mozdev.org
parents: 26113
diff changeset
   801
                if pointer > 1:
26170
61124bf8485f minirst: handle edge in hunting for parents
timeless@mozdev.org
parents: 26157
diff changeset
   802
                    blevel = secs[-pointer][1]
61124bf8485f minirst: handle edge in hunting for parents
timeless@mozdev.org
parents: 26157
diff changeset
   803
                    if section['type'] != b['type']:
61124bf8485f minirst: handle edge in hunting for parents
timeless@mozdev.org
parents: 26157
diff changeset
   804
                        blevel += 1
61124bf8485f minirst: handle edge in hunting for parents
timeless@mozdev.org
parents: 26157
diff changeset
   805
                    secs.append(('', blevel, []))
15014
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   806
            secs[-1][2].append(b)
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   807
    return secs
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   808
15039
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   809
def maketable(data, indent=0, header=False):
16815
e740746ea557 minirst: generate tables as a list of joined lines
Olav Reinert <seroton10@gmail.com>
parents: 15861
diff changeset
   810
    '''Generate an RST table for the given table data as a list of lines'''
15039
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   811
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   812
    widths = [max(encoding.colwidth(e) for e in c) for c in zip(*data)]
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   813
    indent = ' ' * indent
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   814
    div = indent + ' '.join('=' * w for w in widths) + '\n'
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   815
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   816
    out = [div]
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   817
    for row in data:
15144
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   818
        l = []
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   819
        for w, v in zip(widths, row):
20654
af9d9b778550 minirst: create valid output when table data contains a newline
Simon Heimberg <simohe@besonet.ch>
parents: 20549
diff changeset
   820
            if '\n' in v:
af9d9b778550 minirst: create valid output when table data contains a newline
Simon Heimberg <simohe@besonet.ch>
parents: 20549
diff changeset
   821
                # only remove line breaks and indentation, long lines are
af9d9b778550 minirst: create valid output when table data contains a newline
Simon Heimberg <simohe@besonet.ch>
parents: 20549
diff changeset
   822
                # handled by the next tool
af9d9b778550 minirst: create valid output when table data contains a newline
Simon Heimberg <simohe@besonet.ch>
parents: 20549
diff changeset
   823
                v = ' '.join(e.lstrip() for e in v.split('\n'))
15144
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   824
            pad = ' ' * (w - encoding.colwidth(v))
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   825
            l.append(v + pad)
87bb975a1844 minirst: fix column handling for simple tables
Matt Mackall <mpm@selenic.com>
parents: 15125
diff changeset
   826
        out.append(indent + ' '.join(l) + "\n")
15039
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   827
    if header and len(data) > 1:
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   828
        out.insert(2, div)
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   829
    out.append(div)
16815
e740746ea557 minirst: generate tables as a list of joined lines
Olav Reinert <seroton10@gmail.com>
parents: 15861
diff changeset
   830
    return out