#!/usr/bin/env python
# emacs: -*- coding: utf-8; mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:

### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
#
#   See COPYING file distributed along with the PyMVPA package for the
#   copyright and license terms.
#
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
"""Helper to automagically generate ReST versions of cmdline examples"""

__docformat__ = 'restructuredtext'


import os
import sys
import re
import glob
from optparse import OptionParser


def exfile2rst(filename):
    """Open a Python script and convert it into an ReST string.
    """
    # output string
    s = ''

    # open source file
    xfile = open(filename)

    # parser status vars
    inexample = False
    incodeblock = False

    for line in xfile:
        if line.startswith('#% EXAMPLE START'):
            inexample = True
            continue
        if line.startswith('#% EXAMPLE END'):
            break
        if not inexample:
            continue
        if line.startswith('#% '):
            incodeblock = False
            s += line[3:]
            continue
        if incodeblock:
            s += '  %s' % line
            continue
        # normal line
        else:
            if len(line.strip()):
                incodeblock = True
                s += '\n.. code-block:: sh\n\n  %s' % line

    xfile.close()

    return s


def exfile2rstfile(filename, opts):
    """
    """
    #  doc filename
    dfilename = os.path.basename(filename[:-3]) + '.rst'

    # open dest file
    dfile = open(os.path.join(opts.outdir, os.path.basename(dfilename)), 'w')

    # place header
    dfile.write('.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n')

    # place cross-ref target
    dfile.write('.. _example_cmdline_' + dfilename[:-4] + ':\n\n')

    # write converted ReST
    dfile.write(exfile2rst(filename))

    if opts.sourceref:
        # write post example see also box
        dfile.write("\n.. seealso::\n  The full source code of this example is "
                    "included in the %s source distribution (`%s`).\n"
                    % (opts.project, filename))

    dfile.close()



def main():
    parser = OptionParser( \
        usage="%prog [options] <filename|directory> [...]", \
        version="%prog 0.1", description="""\
%prog converts Python scripts into restructered text (ReST) format suitable for
integration into the Sphinx documentation framework. Its key feature is that it
extracts stand-alone (unassigned) single, or multiline triple-quote docstrings
and moves them out of the code listing so that they are rendered as regular
ReST, while at the same time maintaining their position relative to the
listing.

The detection of such docstrings is exclusively done by parsing the raw code so
it is never actually imported into a running Python session. Docstrings have to
be written using triple quotes (both forms " and ' are possible).

It is recommend that such docstrings are preceded and followed by an empty line.
Intended docstring can make use of the full linewidth from the second docstring
line on. If the indentation of multiline docstring is maintained for all lines,
the respective indentation is removed in the ReST output.

The parser algorithm automatically excludes file headers and starts with the
first (module-level) docstring instead.
""" )

    # define options
    parser.add_option('--verbose', action='store_true', dest='verbose',
                      default=False, help='print status messages')
    parser.add_option('-x', '--exclude', action='append', dest='excluded',
                      help="""\
Use this option to exclude single files from the to be parsed files. This is
especially useful to exclude files when parsing complete directories. This
option can be specified multiple times.
""")
    parser.add_option('-o', '--outdir', action='store', dest='outdir',
                      type='string', default=None, help="""\
Target directory to write the ReST output to. This is a required option.
""")
    parser.add_option('--no-sourceref', action='store_false', default=True,
                      dest='sourceref', help="""\
If specified, the source reference section will be suppressed.
""")
    parser.add_option('--project', type='string', action='store', default='',
                      dest='project', help="""\
Name of the project that contains the examples. This name is used in the
'seealso' source references. Default: ''
""")

    # parse options
    (opts, args) = parser.parse_args() # read sys.argv[1:] by default

    # check for required options
    if opts.outdir is None:
        print('Required option -o, --outdir not specified.')
        sys.exit(1)

    # build up list of things to parse
    toparse = []
    for t in args:
        # expand dirs
        if os.path.isdir(t):
            # add all python files in that dir
            toparse += glob.glob(os.path.join(t, '*.sh'))
        else:
            toparse.append(t)

    # filter parse list
    if not opts.excluded is None:
        toparse = [t for t in toparse if not t in opts.excluded]

    toparse_list = toparse
    toparse = set(toparse)

    if len(toparse) != len(toparse_list):
        print('Ignoring duplicate parse targets.')

    if not os.path.exists(opts.outdir):
        os.mkdir(opts.outdir)

    # finally process all examples
    for t in toparse:
        exfile2rstfile(t, opts)


if __name__ == '__main__':
    main()
