about summary refs log tree commit diff
path: root/src/etc/sugarise-doc-comments.py
blob: 7bd4175fbf0db9e0d0ac9009137ee188fc06e7fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#!/usr/bin/env python
# xfail-license

#
# this script attempts to turn doc comment attributes (#[doc = "..."])
# into sugared-doc-comments (/** ... */ and /// ...)
#
# it sugarises all .rs/.rc files underneath the working directory
#

import sys, os, fnmatch, re


DOC_PATTERN = '^(?P<indent>[\\t ]*)#\\[(\\s*)doc(\\s*)=' + \
              '(\\s*)"(?P<text>(\\"|[^"])*?)"(\\s*)\\]' + \
              '(?P<semi>;)?'

ESCAPES = [("\\'", "'"),
           ('\\"', '"'),
           ("\\n", "\n"),
           ("\\r", "\r"),
           ("\\t", "\t")]


def unescape(s):
    for (find, repl) in ESCAPES:
        s = s.replace(find, repl)
    return s


def block_trim(s):
    lns = s.splitlines()

    # remove leading/trailing whitespace-lines
    while lns and not lns[0].strip():
        lns = lns[1:]
    while lns and not lns[-1].strip():
        lns = lns[:-1]

    # remove leading horizontal whitespace
    n = sys.maxint
    for ln in lns:
        if ln.strip():
            n = min(n, len(re.search('^\s*', ln).group()))
    if n != sys.maxint:
        lns = [ln[n:] for ln in lns]

    # strip trailing whitespace
    lns = [ln.rstrip() for ln in lns]

    return lns


def replace_doc(m):
    indent = m.group('indent')
    text = block_trim(unescape(m.group('text')))

    if len(text) > 1:
        inner = '!' if m.group('semi') else '*'
        starify = lambda s: indent + ' *' + (' ' + s if s else '')
        text = '\n'.join(map(starify, text))
        repl = indent + '/*' + inner + '\n' + text + '\n' + indent + ' */'
    else:
        inner = '!' if m.group('semi') else '/'
        repl = indent + '//' + inner + ' ' + text[0]

    return repl


def sugarise_file(path):
    s = open(path).read()

    r = re.compile(DOC_PATTERN, re.MULTILINE | re.DOTALL)
    ns = re.sub(r, replace_doc, s)

    if s != ns:
        open(path, 'w').write(ns)


for (dirpath, dirnames, filenames) in os.walk('.'):
    for name in fnmatch.filter(filenames, '*.r[sc]'):
        sugarise_file(os.path.join(dirpath, name))