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