mercurial/minirst.py
author Martin Geisler <mg@aragost.com>
Wed, 17 Aug 2011 14:11:46 +0200
changeset 15041 3afe5edda4e3
parent 15039 c981f4a9ea74
child 15102 a7e375d087f6
permissions -rw-r--r--
merge: use repo.ui directly instead local variable The non-standard 'u = repo.ui' shorthand was only used two times and there were many other full references to repo.ui.
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
12958
8957c39867f6 minirst: link to HelpStyleGuide in docstring
Martin Geisler <mg@aragost.com>
parents: 12867
diff changeset
    17
Remember to update http://mercurial.selenic.com/wiki/HelpStyleGuide
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
15038
3f4d337cb80a minirst: drop debug code
Matt Mackall <mpm@selenic.com>
parents: 15037
diff changeset
    21
import re
11464
521c8e0c93bf minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11297
diff changeset
    22
import util, encoding
12388
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
    23
from i18n import _
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
    24
11464
521c8e0c93bf minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11297
diff changeset
    25
521c8e0c93bf minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11297
diff changeset
    26
def replace(text, substs):
521c8e0c93bf minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11297
diff changeset
    27
    utext = text.decode(encoding.encoding)
521c8e0c93bf minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11297
diff changeset
    28
    for f, t in substs:
521c8e0c93bf minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11297
diff changeset
    29
        utext = utext.replace(f, t)
521c8e0c93bf minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11297
diff changeset
    30
    return utext.encode(encoding.encoding)
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    31
12651
17f28de168a4 minirst: refactor/simplify findblocks
Martin Geisler <mg@lazybytes.net>
parents: 12620
diff changeset
    32
17f28de168a4 minirst: refactor/simplify findblocks
Martin Geisler <mg@lazybytes.net>
parents: 12620
diff changeset
    33
_blockre = re.compile(r"\n(?:\s*\n)+")
17f28de168a4 minirst: refactor/simplify findblocks
Martin Geisler <mg@lazybytes.net>
parents: 12620
diff changeset
    34
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    35
def findblocks(text):
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    36
    """Find continuous blocks of lines in text.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    37
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    38
    Returns a list of dictionaries representing the blocks. Each block
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    39
    has an 'indent' field and a 'lines' field.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    40
    """
12651
17f28de168a4 minirst: refactor/simplify findblocks
Martin Geisler <mg@lazybytes.net>
parents: 12620
diff changeset
    41
    blocks = []
15036
bb96e12a3242 minirst: only strip leading newlines, not indentation
Matt Mackall <mpm@selenic.com>
parents: 15015
diff changeset
    42
    for b in _blockre.split(text.lstrip('\n').rstrip()):
12651
17f28de168a4 minirst: refactor/simplify findblocks
Martin Geisler <mg@lazybytes.net>
parents: 12620
diff changeset
    43
        lines = b.splitlines()
17f28de168a4 minirst: refactor/simplify findblocks
Martin Geisler <mg@lazybytes.net>
parents: 12620
diff changeset
    44
        indent = min((len(l) - len(l.lstrip())) for l in lines)
17f28de168a4 minirst: refactor/simplify findblocks
Martin Geisler <mg@lazybytes.net>
parents: 12620
diff changeset
    45
        lines = [l[indent:] for l in lines]
17f28de168a4 minirst: refactor/simplify findblocks
Martin Geisler <mg@lazybytes.net>
parents: 12620
diff changeset
    46
        blocks.append(dict(indent=indent, lines=lines))
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    47
    return blocks
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    48
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    49
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    50
def findliteralblocks(blocks):
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    51
    """Finds literal blocks and adds a 'type' field to the blocks.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    52
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    53
    Literal blocks are given the type 'literal', all other blocks are
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    54
    given type the 'paragraph'.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    55
    """
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    56
    i = 0
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    57
    while i < len(blocks):
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    58
        # Searching for a block that looks like this:
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    59
        #
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    60
        # +------------------------------+
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    61
        # | paragraph                    |
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    62
        # | (ends with "::")             |
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    63
        # +------------------------------+
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    64
        #    +---------------------------+
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    65
        #    | indented literal block    |
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    66
        #    +---------------------------+
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    67
        blocks[i]['type'] = 'paragraph'
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
    68
        if blocks[i]['lines'][-1].endswith('::') and i + 1 < len(blocks):
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    69
            indent = blocks[i]['indent']
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
    70
            adjustment = blocks[i + 1]['indent'] - indent
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    71
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    72
            if blocks[i]['lines'] == ['::']:
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    73
                # Expanded form: remove block
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    74
                del blocks[i]
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    75
                i -= 1
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    76
            elif blocks[i]['lines'][-1].endswith(' ::'):
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    77
                # Partially minimized form: remove space and both
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    78
                # colons.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    79
                blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-3]
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    80
            else:
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    81
                # Fully minimized form: remove just one colon.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    82
                blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-1]
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    83
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    84
            # List items are formatted with a hanging indent. We must
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    85
            # correct for this here while we still have the original
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    86
            # information on the indentation of the subsequent literal
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    87
            # blocks available.
9738
f52c4f7a4732 minirst: prepare for general types of bullet lists
Martin Geisler <mg@lazybytes.net>
parents: 9737
diff changeset
    88
            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
    89
            if m:
f52c4f7a4732 minirst: prepare for general types of bullet lists
Martin Geisler <mg@lazybytes.net>
parents: 9737
diff changeset
    90
                indent += m.end()
f52c4f7a4732 minirst: prepare for general types of bullet lists
Martin Geisler <mg@lazybytes.net>
parents: 9737
diff changeset
    91
                adjustment -= m.end()
9156
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
            # Mark the following indented blocks.
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
    94
            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
    95
                blocks[i + 1]['type'] = 'literal'
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
    96
                blocks[i + 1]['indent'] -= adjustment
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    97
                i += 1
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    98
        i += 1
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
    99
    return blocks
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   100
10447
e957cc7cbd14 minirst: support line blocks
Martin Geisler <mg@lazybytes.net>
parents: 10444
diff changeset
   101
_bulletre = re.compile(r'(-|[0-9A-Za-z]+\.|\(?[0-9A-Za-z]+\)|\|) ')
13011
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   102
_optionre = re.compile(r'^(-([a-zA-Z0-9]), )?(--[a-z0-9-]+)'
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   103
                       r'((.*)  +)(.*)$')
10065
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   104
_fieldre = re.compile(r':(?![: ])([^:]*)(?<! ):[ ]+(.*)')
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   105
_definitionre = re.compile(r'[^ ]')
15037
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   106
_tablere = re.compile(r'(=+\s+)*=+')
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   107
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   108
def splitparagraphs(blocks):
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   109
    """Split paragraphs into lists."""
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   110
    # 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
   111
    # 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
   112
    # come last.
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   113
    listtypes = [('bullet', _bulletre, True),
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   114
                 ('option', _optionre, True),
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   115
                 ('field', _fieldre, True),
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   116
                 ('definition', _definitionre, False)]
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   117
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   118
    def match(lines, i, itemre, singleline):
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   119
        """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
   120
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   121
        A list item can be followed by an idented line or another list
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   122
        item (but only if singleline is True).
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   123
        """
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   124
        line1 = lines[i]
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   125
        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
   126
        if not itemre.match(line1):
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   127
            return False
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   128
        if singleline:
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   129
            return line2 == '' or line2[0] == ' ' or itemre.match(line2)
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   130
        else:
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   131
            return line2.startswith(' ')
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   132
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   133
    i = 0
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   134
    while i < len(blocks):
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   135
        if blocks[i]['type'] == 'paragraph':
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   136
            lines = blocks[i]['lines']
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   137
            for type, itemre, singleline in listtypes:
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   138
                if match(lines, 0, itemre, singleline):
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   139
                    items = []
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   140
                    for j, line in enumerate(lines):
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   141
                        if match(lines, j, itemre, singleline):
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   142
                            items.append(dict(type=type, lines=[],
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   143
                                              indent=blocks[i]['indent']))
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   144
                        items[-1]['lines'].append(line)
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   145
                    blocks[i:i + 1] = items
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   146
                    break
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   147
        i += 1
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   148
    return blocks
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   149
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   150
10065
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   151
_fieldwidth = 12
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   152
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   153
def updatefieldlists(blocks):
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   154
    """Find key and maximum key width for field lists."""
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   155
    i = 0
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   156
    while i < len(blocks):
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   157
        if blocks[i]['type'] != 'field':
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   158
            i += 1
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   159
            continue
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   160
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   161
        keywidth = 0
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   162
        j = i
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   163
        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
   164
            m = _fieldre.match(blocks[j]['lines'][0])
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   165
            key, rest = m.groups()
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   166
            blocks[j]['lines'][0] = rest
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   167
            blocks[j]['key'] = key
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   168
            keywidth = max(keywidth, len(key))
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   169
            j += 1
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   170
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   171
        for block in blocks[i:j]:
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   172
            block['keywidth'] = keywidth
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   173
        i = j + 1
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   174
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   175
    return blocks
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   176
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   177
13011
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   178
def updateoptionlists(blocks):
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   179
    i = 0
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   180
    while i < len(blocks):
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   181
        if blocks[i]['type'] != 'option':
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   182
            i += 1
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   183
            continue
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   184
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   185
        optstrwidth = 0
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   186
        j = i
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   187
        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
   188
            m = _optionre.match(blocks[j]['lines'][0])
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   189
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   190
            shortoption = m.group(2)
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   191
            group3 = m.group(3)
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   192
            longoption = group3[2:].strip()
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   193
            desc = m.group(6).strip()
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   194
            longoptionarg = m.group(5).strip()
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   195
            blocks[j]['lines'][0] = desc
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   196
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   197
            noshortop = ''
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   198
            if not shortoption:
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   199
                noshortop = '   '
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   200
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   201
            opt = "%s%s" %   (shortoption and "-%s " % shortoption or '',
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   202
                            ("%s--%s %s") % (noshortop, longoption,
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   203
                                             longoptionarg))
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   204
            opt = opt.rstrip()
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   205
            blocks[j]['optstr'] = opt
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   206
            optstrwidth = max(optstrwidth, encoding.colwidth(opt))
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   207
            j += 1
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   208
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   209
        for block in blocks[i:j]:
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   210
            block['optstrwidth'] = optstrwidth
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   211
        i = j + 1
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   212
    return blocks
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   213
10443
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   214
def prunecontainers(blocks, keep):
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   215
    """Prune unwanted containers.
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   216
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   217
    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
   218
    run through findliteralblocks first.
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   219
    """
10444
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   220
    pruned = []
10443
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   221
    i = 0
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   222
    while i + 1 < len(blocks):
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   223
        # Searching for a block that looks like this:
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   224
        #
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   225
        # +-------+---------------------------+
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   226
        # | ".. container ::" type            |
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   227
        # +---+                               |
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   228
        #     | blocks                        |
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   229
        #     +-------------------------------+
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   230
        if (blocks[i]['type'] == 'paragraph' and
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   231
            blocks[i]['lines'][0].startswith('.. container::')):
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   232
            indent = blocks[i]['indent']
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   233
            adjustment = blocks[i + 1]['indent'] - indent
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   234
            containertype = blocks[i]['lines'][0][15:]
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   235
            prune = containertype not in keep
10444
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   236
            if prune:
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   237
                pruned.append(containertype)
10443
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   238
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   239
            # Always delete "..container:: type" block
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   240
            del blocks[i]
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   241
            j = i
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   242
            while j < len(blocks) and blocks[j]['indent'] > indent:
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   243
                if prune:
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   244
                    del blocks[j]
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   245
                    i -= 1 # adjust outer index
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   246
                else:
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   247
                    blocks[j]['indent'] -= adjustment
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   248
                    j += 1
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   249
        i += 1
10444
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   250
    return blocks, pruned
10443
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   251
62d484a81dfe minirst: support containers
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   252
10984
68b7d2d668ce minirst: support all recommended title adornments
Martin Geisler <mg@lazybytes.net>
parents: 10983
diff changeset
   253
_sectionre = re.compile(r"""^([-=`:.'"~^_*+#])\1+$""")
68b7d2d668ce minirst: support all recommended title adornments
Martin Geisler <mg@lazybytes.net>
parents: 10983
diff changeset
   254
15037
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   255
def findtables(blocks):
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   256
    '''Find simple tables
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   257
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   258
       Only simple one-line table elements are supported
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   259
    '''
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   260
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   261
    for block in blocks:
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   262
        # Searching for a block that looks like this:
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   263
        #
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   264
        # === ==== ===
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   265
        #  A    B   C
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   266
        # === ==== ===  <- optional
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   267
        #  1    2   3
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   268
        #  x    y   z
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   269
        # === ==== ===
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   270
        if (block['type'] == 'paragraph' and
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   271
            len(block['lines']) > 4 and
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   272
            _tablere.match(block['lines'][0]) and
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   273
            block['lines'][0] == block['lines'][-1]):
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   274
            block['type'] = 'table'
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   275
            block['header'] = False
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   276
            div = block['lines'][0]
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   277
            columns = [x for x in xrange(len(div))
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   278
                       if div[x] == '=' and (x == 0 or div[x - 1] == ' ')]
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   279
            rows = []
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   280
            for l in block['lines'][1:-1]:
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   281
                if l == div:
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   282
                    block['header'] = True
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   283
                    continue
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   284
                row = []
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   285
                for n, start in enumerate(columns):
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   286
                    if n + 1 < len(columns):
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   287
                        row.append(l[start:columns[n + 1]].strip())
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   288
                    else:
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   289
                        row.append(l[start:].strip())
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   290
                rows.append(row)
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   291
            block['table'] = rows
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   292
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   293
    return blocks
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   294
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   295
def findsections(blocks):
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   296
    """Finds sections.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   297
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   298
    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
   299
    run through findliteralblocks first.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   300
    """
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   301
    for block in blocks:
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   302
        # Searching for a block that looks like this:
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   303
        #
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   304
        # +------------------------------+
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   305
        # | Section title                |
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   306
        # | -------------                |
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   307
        # +------------------------------+
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   308
        if (block['type'] == 'paragraph' and
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   309
            len(block['lines']) == 2 and
12867
eda77c3e246a minirst: use colwidth to match title lengths (issue2455)
Matt Mackall <mpm@selenic.com>
parents: 12819
diff changeset
   310
            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
   311
            _sectionre.match(block['lines'][1])):
10983
287a5cdf7743 minirst: correctly format sections containing inline markup
Martin Geisler <mg@lazybytes.net>
parents: 10972
diff changeset
   312
            block['underline'] = block['lines'][1][0]
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   313
            block['type'] = 'section'
10983
287a5cdf7743 minirst: correctly format sections containing inline markup
Martin Geisler <mg@lazybytes.net>
parents: 10972
diff changeset
   314
            del block['lines'][1]
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   315
    return blocks
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   316
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   317
9623
32727ce029de minirst: convert ``foo`` into "foo" upon display
Martin Geisler <mg@lazybytes.net>
parents: 9540
diff changeset
   318
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
   319
    substs = [('``', '"')]
9623
32727ce029de minirst: convert ``foo`` into "foo" upon display
Martin Geisler <mg@lazybytes.net>
parents: 9540
diff changeset
   320
    for b in blocks:
10983
287a5cdf7743 minirst: correctly format sections containing inline markup
Martin Geisler <mg@lazybytes.net>
parents: 10972
diff changeset
   321
        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
   322
            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
   323
    return blocks
32727ce029de minirst: convert ``foo`` into "foo" upon display
Martin Geisler <mg@lazybytes.net>
parents: 9540
diff changeset
   324
32727ce029de minirst: convert ``foo`` into "foo" upon display
Martin Geisler <mg@lazybytes.net>
parents: 9540
diff changeset
   325
10972
0a2c6948f5f4 doc, minirst: support hg interpreted text role
Martin Geisler <mg@aragost.com>
parents: 10937
diff changeset
   326
def hgrole(blocks):
11464
521c8e0c93bf minirst: use unicode string as intermediate form for replacement
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11297
diff changeset
   327
    substs = [(':hg:`', '"hg '), ('`', '"')]
10972
0a2c6948f5f4 doc, minirst: support hg interpreted text role
Martin Geisler <mg@aragost.com>
parents: 10937
diff changeset
   328
    for b in blocks:
10983
287a5cdf7743 minirst: correctly format sections containing inline markup
Martin Geisler <mg@lazybytes.net>
parents: 10972
diff changeset
   329
        if b['type'] in ('paragraph', 'section'):
11192
babf9a5f5528 minirst: handle line breaks in hg role
Martin Geisler <mg@aragost.com>
parents: 11189
diff changeset
   330
            # 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
   331
            # 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
   332
            # 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
   333
            # (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
   334
            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
   335
    return blocks
0a2c6948f5f4 doc, minirst: support hg interpreted text role
Martin Geisler <mg@aragost.com>
parents: 10937
diff changeset
   336
0a2c6948f5f4 doc, minirst: support hg interpreted text role
Martin Geisler <mg@aragost.com>
parents: 10937
diff changeset
   337
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   338
def addmargins(blocks):
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   339
    """Adds empty blocks for vertical spacing.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   340
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   341
    This groups bullets, options, and definitions together with no vertical
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   342
    space between them, and adds an empty block between all other blocks.
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   343
    """
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   344
    i = 1
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   345
    while i < len(blocks):
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
   346
        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
   347
            blocks[i]['type'] in ('bullet', 'option', 'field')):
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   348
            i += 1
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   349
        else:
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   350
            blocks.insert(i, dict(lines=[''], indent=0, type='margin'))
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   351
            i += 2
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   352
    return blocks
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   353
12819
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   354
def prunecomments(blocks):
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   355
    """Remove comments."""
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   356
    i = 0
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   357
    while i < len(blocks):
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   358
        b = blocks[i]
13009
54be08fa4d1d minirst: modified minirst to also recognize empty comments.
Erik Zielke <ez@aragost.com>
parents: 13003
diff changeset
   359
        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
   360
                                         b['lines'] == ['..']):
12819
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   361
            del blocks[i]
13003
876a931dd230 minirst: better interaction between comments and margins
Martin Geisler <mg@aragost.com>
parents: 12958
diff changeset
   362
            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
   363
                del blocks[i]
12819
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   364
        else:
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   365
            i += 1
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   366
    return blocks
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   367
12620
9a9312e84e4e minirst: small code cleanup
Martin Geisler <mg@lazybytes.net>
parents: 12388
diff changeset
   368
_admonitionre = re.compile(r"\.\. (admonition|attention|caution|danger|"
9a9312e84e4e minirst: small code cleanup
Martin Geisler <mg@lazybytes.net>
parents: 12388
diff changeset
   369
                           r"error|hint|important|note|tip|warning)::",
9a9312e84e4e minirst: small code cleanup
Martin Geisler <mg@lazybytes.net>
parents: 12388
diff changeset
   370
                           flags=re.IGNORECASE)
9a9312e84e4e minirst: small code cleanup
Martin Geisler <mg@lazybytes.net>
parents: 12388
diff changeset
   371
12388
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   372
def findadmonitions(blocks):
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   373
    """
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   374
    Makes the type of the block an admonition block if
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   375
    the first line is an admonition directive
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   376
    """
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   377
    i = 0
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   378
    while i < len(blocks):
12620
9a9312e84e4e minirst: small code cleanup
Martin Geisler <mg@lazybytes.net>
parents: 12388
diff changeset
   379
        m = _admonitionre.match(blocks[i]['lines'][0])
12388
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   380
        if m:
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   381
            blocks[i]['type'] = 'admonition'
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   382
            admonitiontitle = blocks[i]['lines'][0][3:m.end() - 2].lower()
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   383
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   384
            firstline = blocks[i]['lines'][0][m.end() + 1:]
12620
9a9312e84e4e minirst: small code cleanup
Martin Geisler <mg@lazybytes.net>
parents: 12388
diff changeset
   385
            if firstline:
9a9312e84e4e minirst: small code cleanup
Martin Geisler <mg@lazybytes.net>
parents: 12388
diff changeset
   386
                blocks[i]['lines'].insert(1, '   ' + firstline)
12388
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   387
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   388
            blocks[i]['admonitiontitle'] = admonitiontitle
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   389
            del blocks[i]['lines'][0]
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   390
        i = i + 1
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   391
    return blocks
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   392
12652
3c31c0e42b11 minirst: pull admonition titles out formatblock function
Martin Geisler <mg@lazybytes.net>
parents: 12651
diff changeset
   393
_admonitiontitles = {'attention': _('Attention:'),
3c31c0e42b11 minirst: pull admonition titles out formatblock function
Martin Geisler <mg@lazybytes.net>
parents: 12651
diff changeset
   394
                     'caution': _('Caution:'),
3c31c0e42b11 minirst: pull admonition titles out formatblock function
Martin Geisler <mg@lazybytes.net>
parents: 12651
diff changeset
   395
                     'danger': _('!Danger!')  ,
3c31c0e42b11 minirst: pull admonition titles out formatblock function
Martin Geisler <mg@lazybytes.net>
parents: 12651
diff changeset
   396
                     'error': _('Error:'),
3c31c0e42b11 minirst: pull admonition titles out formatblock function
Martin Geisler <mg@lazybytes.net>
parents: 12651
diff changeset
   397
                     'hint': _('Hint:'),
3c31c0e42b11 minirst: pull admonition titles out formatblock function
Martin Geisler <mg@lazybytes.net>
parents: 12651
diff changeset
   398
                     'important': _('Important:'),
3c31c0e42b11 minirst: pull admonition titles out formatblock function
Martin Geisler <mg@lazybytes.net>
parents: 12651
diff changeset
   399
                     'note': _('Note:'),
3c31c0e42b11 minirst: pull admonition titles out formatblock function
Martin Geisler <mg@lazybytes.net>
parents: 12651
diff changeset
   400
                     'tip': _('Tip:'),
3c31c0e42b11 minirst: pull admonition titles out formatblock function
Martin Geisler <mg@lazybytes.net>
parents: 12651
diff changeset
   401
                     'warning': _('Warning!')}
3c31c0e42b11 minirst: pull admonition titles out formatblock function
Martin Geisler <mg@lazybytes.net>
parents: 12651
diff changeset
   402
13011
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   403
def formatoption(block, width):
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   404
    desc = ' '.join(map(str.strip, block['lines']))
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   405
    colwidth = encoding.colwidth(block['optstr'])
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   406
    usablewidth = width - 1
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   407
    hanging = block['optstrwidth']
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   408
    initindent = '%s%s  ' % (block['optstr'], ' ' * ((hanging - colwidth)))
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   409
    hangindent = ' ' * (encoding.colwidth(initindent) + 1)
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   410
    return ' %s' % (util.wrap(desc, usablewidth,
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   411
                                           initindent=initindent,
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   412
                                           hangindent=hangindent))
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   413
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   414
def formatblock(block, width):
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   415
    """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
   416
    if width <= 0:
4c3fb45123e5 util, minirst: do not crash with COLUMNS=0
Martin Geisler <mg@lazybytes.net>
parents: 9293
diff changeset
   417
        width = 78
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   418
    indent = ' ' * block['indent']
12388
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   419
    if block['type'] == 'admonition':
12652
3c31c0e42b11 minirst: pull admonition titles out formatblock function
Martin Geisler <mg@lazybytes.net>
parents: 12651
diff changeset
   420
        admonition = _admonitiontitles[block['admonitiontitle']]
12388
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   421
        hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   422
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   423
        defindent = indent + hang * ' '
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   424
        text = ' '.join(map(str.strip, block['lines']))
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   425
        return '%s\n%s' % (indent + admonition, util.wrap(text, width=width,
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   426
                                           initindent=defindent,
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   427
                                           hangindent=defindent))
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   428
    if block['type'] == 'margin':
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   429
        return ''
9735
97d0d910fa5d minirst: remove unnecessary "elif:" statements
Martin Geisler <mg@lazybytes.net>
parents: 9623
diff changeset
   430
    if block['type'] == 'literal':
9291
cd5b6a11b607 minirst: indent literal blocks with two spaces
Martin Geisler <mg@lazybytes.net>
parents: 9156
diff changeset
   431
        indent += '  '
cd5b6a11b607 minirst: indent literal blocks with two spaces
Martin Geisler <mg@lazybytes.net>
parents: 9156
diff changeset
   432
        return indent + ('\n' + indent).join(block['lines'])
9735
97d0d910fa5d minirst: remove unnecessary "elif:" statements
Martin Geisler <mg@lazybytes.net>
parents: 9623
diff changeset
   433
    if block['type'] == 'section':
12867
eda77c3e246a minirst: use colwidth to match title lengths (issue2455)
Matt Mackall <mpm@selenic.com>
parents: 12819
diff changeset
   434
        underline = encoding.colwidth(block['lines'][0]) * block['underline']
10983
287a5cdf7743 minirst: correctly format sections containing inline markup
Martin Geisler <mg@lazybytes.net>
parents: 10972
diff changeset
   435
        return "%s%s\n%s%s" % (indent, block['lines'][0],indent, underline)
15037
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   436
    if block['type'] == 'table':
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   437
        table = block['table']
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   438
        # compute column widths
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   439
        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
   440
        text = ''
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   441
        span = sum(widths) + len(widths) - 1
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   442
        indent = ' ' * block['indent']
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   443
        hang = ' ' * (len(indent) + span - widths[-1])
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   444
        f = ' '.join('%%-%ds' % n for n in widths)
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   445
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   446
        for row in table:
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   447
            l = f % tuple(row)
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   448
            l = util.wrap(l, width=width, initindent=indent, hangindent=hang)
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   449
            if not text and block['header']:
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   450
                text = l + '\n' + indent + '-' * (min(width, span)) + '\n'
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   451
            else:
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   452
                text += l + "\n"
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   453
        return text
9735
97d0d910fa5d minirst: remove unnecessary "elif:" statements
Martin Geisler <mg@lazybytes.net>
parents: 9623
diff changeset
   454
    if block['type'] == 'definition':
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   455
        term = indent + block['lines'][0]
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   456
        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
   457
        defindent = indent + hang * ' '
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   458
        text = ' '.join(map(str.strip, block['lines'][1:]))
11297
d320e70442a5 replace Python standard textwrap by MBCS sensitive one for i18n text
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11192
diff changeset
   459
        return '%s\n%s' % (term, util.wrap(text, width=width,
d320e70442a5 replace Python standard textwrap by MBCS sensitive one for i18n text
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11192
diff changeset
   460
                                           initindent=defindent,
d320e70442a5 replace Python standard textwrap by MBCS sensitive one for i18n text
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11192
diff changeset
   461
                                           hangindent=defindent))
10937
a9d5943d2a30 minirst: removed unnecessary initindent variable
Martin Geisler <mg@lazybytes.net>
parents: 10936
diff changeset
   462
    subindent = indent
9735
97d0d910fa5d minirst: remove unnecessary "elif:" statements
Martin Geisler <mg@lazybytes.net>
parents: 9623
diff changeset
   463
    if block['type'] == 'bullet':
10447
e957cc7cbd14 minirst: support line blocks
Martin Geisler <mg@lazybytes.net>
parents: 10444
diff changeset
   464
        if block['lines'][0].startswith('| '):
e957cc7cbd14 minirst: support line blocks
Martin Geisler <mg@lazybytes.net>
parents: 10444
diff changeset
   465
            # Remove bullet for line blocks and add no extra
e957cc7cbd14 minirst: support line blocks
Martin Geisler <mg@lazybytes.net>
parents: 10444
diff changeset
   466
            # indention.
e957cc7cbd14 minirst: support line blocks
Martin Geisler <mg@lazybytes.net>
parents: 10444
diff changeset
   467
            block['lines'][0] = block['lines'][0][2:]
e957cc7cbd14 minirst: support line blocks
Martin Geisler <mg@lazybytes.net>
parents: 10444
diff changeset
   468
        else:
e957cc7cbd14 minirst: support line blocks
Martin Geisler <mg@lazybytes.net>
parents: 10444
diff changeset
   469
            m = _bulletre.match(block['lines'][0])
e957cc7cbd14 minirst: support line blocks
Martin Geisler <mg@lazybytes.net>
parents: 10444
diff changeset
   470
            subindent = indent + m.end() * ' '
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   471
    elif block['type'] == 'field':
10065
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   472
        keywidth = block['keywidth']
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   473
        key = block['key']
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   474
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   475
        subindent = indent + _fieldwidth * ' '
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   476
        if len(key) + 2 > _fieldwidth:
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   477
            # key too large, use full line width
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   478
            key = key.ljust(width)
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   479
        elif keywidth + 2 < _fieldwidth:
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   480
            # all keys are small, add only two spaces
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   481
            key = key.ljust(keywidth + 2)
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   482
            subindent = indent + (keywidth + 2) * ' '
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   483
        else:
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   484
            # mixed sizes, use fieldwidth for this one
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   485
            key = key.ljust(_fieldwidth)
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   486
        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
   487
    elif block['type'] == 'option':
13011
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   488
        return formatoption(block, width)
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   489
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   490
    text = ' '.join(map(str.strip, block['lines']))
11297
d320e70442a5 replace Python standard textwrap by MBCS sensitive one for i18n text
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11192
diff changeset
   491
    return util.wrap(text, width=width,
d320e70442a5 replace Python standard textwrap by MBCS sensitive one for i18n text
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11192
diff changeset
   492
                     initindent=indent,
d320e70442a5 replace Python standard textwrap by MBCS sensitive one for i18n text
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 11192
diff changeset
   493
                     hangindent=subindent)
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   494
15012
ee766af457ed minirst: add parse method to get document structure
Matt Mackall <mpm@selenic.com>
parents: 14433
diff changeset
   495
def parse(text, indent=0, keep=None):
ee766af457ed minirst: add parse method to get document structure
Matt Mackall <mpm@selenic.com>
parents: 14433
diff changeset
   496
    """Parse text into a list of blocks"""
ee766af457ed minirst: add parse method to get document structure
Matt Mackall <mpm@selenic.com>
parents: 14433
diff changeset
   497
    pruned = []
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   498
    blocks = findblocks(text)
9540
cad36e496640 help: un-indent help topics
Martin Geisler <mg@lazybytes.net>
parents: 9417
diff changeset
   499
    for b in blocks:
cad36e496640 help: un-indent help topics
Martin Geisler <mg@lazybytes.net>
parents: 9417
diff changeset
   500
        b['indent'] += indent
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   501
    blocks = findliteralblocks(blocks)
15037
df47381b41d6 minirst: add simple table support
Matt Mackall <mpm@selenic.com>
parents: 15036
diff changeset
   502
    blocks = findtables(blocks)
10444
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   503
    blocks, pruned = prunecontainers(blocks, keep or [])
10983
287a5cdf7743 minirst: correctly format sections containing inline markup
Martin Geisler <mg@lazybytes.net>
parents: 10972
diff changeset
   504
    blocks = findsections(blocks)
9623
32727ce029de minirst: convert ``foo`` into "foo" upon display
Martin Geisler <mg@lazybytes.net>
parents: 9540
diff changeset
   505
    blocks = inlineliterals(blocks)
10972
0a2c6948f5f4 doc, minirst: support hg interpreted text role
Martin Geisler <mg@aragost.com>
parents: 10937
diff changeset
   506
    blocks = hgrole(blocks)
9737
5f101af4a921 minirst: combine list parsing in one function
Martin Geisler <mg@lazybytes.net>
parents: 9735
diff changeset
   507
    blocks = splitparagraphs(blocks)
10065
a1ae0ed78d1a minirst: improve layout of field lists
Martin Geisler <mg@lazybytes.net>
parents: 10064
diff changeset
   508
    blocks = updatefieldlists(blocks)
13011
4936a04b6792 minirst: improved support for option lists.
Erik Zielke <ez@aragost.com>
parents: 13009
diff changeset
   509
    blocks = updateoptionlists(blocks)
13003
876a931dd230 minirst: better interaction between comments and margins
Martin Geisler <mg@aragost.com>
parents: 12958
diff changeset
   510
    blocks = addmargins(blocks)
12819
5082e2f3f8e0 minirst: ignore comments
Martin Geisler <mg@lazybytes.net>
parents: 12652
diff changeset
   511
    blocks = prunecomments(blocks)
12388
75f044d4dbf5 minirst: Support for admonitions
Erik Zielke <ez@aragost.com>
parents: 11464
diff changeset
   512
    blocks = findadmonitions(blocks)
15012
ee766af457ed minirst: add parse method to get document structure
Matt Mackall <mpm@selenic.com>
parents: 14433
diff changeset
   513
    return blocks, pruned
ee766af457ed minirst: add parse method to get document structure
Matt Mackall <mpm@selenic.com>
parents: 14433
diff changeset
   514
15013
4a1e3c761ec7 minirst: add formatblocks helper
Matt Mackall <mpm@selenic.com>
parents: 15012
diff changeset
   515
def formatblocks(blocks, width):
4a1e3c761ec7 minirst: add formatblocks helper
Matt Mackall <mpm@selenic.com>
parents: 15012
diff changeset
   516
    text = '\n'.join(formatblock(b, width) for b in blocks)
4a1e3c761ec7 minirst: add formatblocks helper
Matt Mackall <mpm@selenic.com>
parents: 15012
diff changeset
   517
    return text
4a1e3c761ec7 minirst: add formatblocks helper
Matt Mackall <mpm@selenic.com>
parents: 15012
diff changeset
   518
15012
ee766af457ed minirst: add parse method to get document structure
Matt Mackall <mpm@selenic.com>
parents: 14433
diff changeset
   519
def format(text, width, indent=0, keep=None):
ee766af457ed minirst: add parse method to get document structure
Matt Mackall <mpm@selenic.com>
parents: 14433
diff changeset
   520
    """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
   521
    blocks, pruned = parse(text, indent, keep or [])
10444
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   522
    text = '\n'.join(formatblock(b, width) for b in blocks)
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   523
    if keep is None:
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   524
        return text
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   525
    else:
e99e0e077bc4 minirst: report pruned container types
Martin Geisler <mg@lazybytes.net>
parents: 10443
diff changeset
   526
        return text, pruned
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   527
15014
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   528
def getsections(blocks):
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   529
    '''return a list of (section name, nesting level, blocks) tuples'''
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   530
    nest = ""
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   531
    level = 0
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   532
    secs = []
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   533
    for b in blocks:
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   534
        if b['type'] == 'section':
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   535
            i = b['underline']
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   536
            if i not in nest:
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   537
                nest += i
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   538
            level = nest.index(i) + 1
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   539
            nest = nest[:level]
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   540
            secs.append((b['lines'][0], level, [b]))
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   541
        else:
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   542
            if not secs:
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   543
                # add an initial empty section
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   544
                secs = [('', 0, [])]
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   545
            secs[-1][2].append(b)
a814e986859f minirst: add getsections helper
Matt Mackall <mpm@selenic.com>
parents: 15013
diff changeset
   546
    return secs
9156
c9c7e8cdac9c minimal reStructuredText parser
Martin Geisler <mg@lazybytes.net>
parents:
diff changeset
   547
15015
ee6988aea74e minirst: add decorateblocks search helper
Matt Mackall <mpm@selenic.com>
parents: 15014
diff changeset
   548
def decorateblocks(blocks, width):
ee6988aea74e minirst: add decorateblocks search helper
Matt Mackall <mpm@selenic.com>
parents: 15014
diff changeset
   549
    '''generate a list of (section name, line text) pairs for search'''
ee6988aea74e minirst: add decorateblocks search helper
Matt Mackall <mpm@selenic.com>
parents: 15014
diff changeset
   550
    lines = []
ee6988aea74e minirst: add decorateblocks search helper
Matt Mackall <mpm@selenic.com>
parents: 15014
diff changeset
   551
    for s in getsections(blocks):
ee6988aea74e minirst: add decorateblocks search helper
Matt Mackall <mpm@selenic.com>
parents: 15014
diff changeset
   552
        section = s[0]
ee6988aea74e minirst: add decorateblocks search helper
Matt Mackall <mpm@selenic.com>
parents: 15014
diff changeset
   553
        text = formatblocks(s[2], width)
ee6988aea74e minirst: add decorateblocks search helper
Matt Mackall <mpm@selenic.com>
parents: 15014
diff changeset
   554
        lines.append([(section, l) for l in text.splitlines(True)])
ee6988aea74e minirst: add decorateblocks search helper
Matt Mackall <mpm@selenic.com>
parents: 15014
diff changeset
   555
    return 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
   556
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   557
def maketable(data, indent=0, header=False):
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   558
    '''Generate an RST table for the given table data'''
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   559
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   560
    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
   561
    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
   562
    f = indent + ' '.join('%%-%ds' % 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
   563
    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
   564
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   565
    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
   566
    for row in data:
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   567
        out.append(f % tuple(row))
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   568
    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
   569
        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
   570
    out.append(div)
c981f4a9ea74 minirst: add a helper function to build an RST table from an array
Matt Mackall <mpm@selenic.com>
parents: 15038
diff changeset
   571
    return ''.join(out)