#!/usr/bin/env python
#
# Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.

#
# 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
import os
import fnmatch
import 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))
