"""pip sphinx extensions"""

import optparse
import sys
from textwrap import dedent

from docutils import nodes
from docutils.parsers import rst
from docutils.statemachine import ViewList

from pip._internal.cli import cmdoptions
from pip._internal.commands import create_command
from pip._internal.req.req_file import SUPPORTED_OPTIONS


class PipCommandUsage(rst.Directive):
    required_arguments = 1

    def run(self):
        cmd = create_command(self.arguments[0])
        usage = dedent(
            cmd.usage.replace('%prog', 'pip {}'.format(cmd.name))
        ).strip()
        node = nodes.literal_block(usage, usage)
        return [node]


class PipCommandDescription(rst.Directive):
    required_arguments = 1

    def run(self):
        node = nodes.paragraph()
        node.document = self.state.document
        desc = ViewList()
        cmd = create_command(self.arguments[0])
        description = dedent(cmd.__doc__)
        for line in description.split('\n'):
            desc.append(line, "")
        self.state.nested_parse(desc, 0, node)
        return [node]


class PipOptions(rst.Directive):

    def _format_option(self, option, cmd_name=None):
        bookmark_line = (
            ".. _`{cmd_name}_{option._long_opts[0]}`:"
            if cmd_name else
            ".. _`{option._long_opts[0]}`:"
        ).format(**locals())
        line = ".. option:: "
        if option._short_opts:
            line += option._short_opts[0]
        if option._short_opts and option._long_opts:
            line += ", " + option._long_opts[0]
        elif option._long_opts:
            line += option._long_opts[0]
        if option.takes_value():
            metavar = option.metavar or option.dest.lower()
            line += " <{}>".format(metavar.lower())
        # fix defaults
        opt_help = option.help.replace('%default', str(option.default))
        # fix paths with sys.prefix
        opt_help = opt_help.replace(sys.prefix, "<sys.prefix>")
        return [bookmark_line, "", line, "", "    " + opt_help, ""]

    def _format_options(self, options, cmd_name=None):
        for option in options:
            if option.help == optparse.SUPPRESS_HELP:
                continue
            for line in self._format_option(option, cmd_name):
                self.view_list.append(line, "")

    def run(self):
        node = nodes.paragraph()
        node.document = self.state.document
        self.view_list = ViewList()
        self.process_options()
        self.state.nested_parse(self.view_list, 0, node)
        return [node]


class PipGeneralOptions(PipOptions):
    def process_options(self):
        self._format_options(
            [o() for o in cmdoptions.general_group['options']]
        )


class PipIndexOptions(PipOptions):
    required_arguments = 1

    def process_options(self):
        cmd_name = self.arguments[0]
        self._format_options(
            [o() for o in cmdoptions.index_group['options']],
            cmd_name=cmd_name,
        )


class PipCommandOptions(PipOptions):
    required_arguments = 1

    def process_options(self):
        cmd = create_command(self.arguments[0])
        self._format_options(
            cmd.parser.option_groups[0].option_list,
            cmd_name=cmd.name,
        )


class PipReqFileOptionsReference(PipOptions):

    def process_options(self):
        for option in SUPPORTED_OPTIONS:
            if getattr(option, 'deprecated', False):
                continue

            opt = option()
            opt_name = opt._long_opts[0]
            if opt._short_opts:
                short_opt_name = '{}, '.format(opt._short_opts[0])
            else:
                short_opt_name = ''

            from_install = (
                'install_'
                if option not in cmdoptions.general_group['options'] else
                ''
            )
            self.view_list.append(
                '  *  :ref:`{short}{long}<{prefix}{opt_name}>`'.format(
                    short=short_opt_name,
                    long=opt_name,
                    prefix=from_install,
                    opt_name=opt_name
                ),
                "\n"
            )


def setup(app):
    app.add_directive('pip-command-usage', PipCommandUsage)
    app.add_directive('pip-command-description', PipCommandDescription)
    app.add_directive('pip-command-options', PipCommandOptions)
    app.add_directive('pip-general-options', PipGeneralOptions)
    app.add_directive('pip-index-options', PipIndexOptions)
    app.add_directive(
        'pip-requirements-file-options-ref-list', PipReqFileOptionsReference
    )

@@ -257,16 +257,31 @@
 s import
+ commands_dict,
  create_
@@ -3324,24 +3324,312 @@
 pOptions):%0A%0A
+    def determine_opt_prefix(self, opt_name):%0A        for command in commands_dict:%0A            cmd = create_command(command)%0A            if cmd.cmd_opts.has_option(opt_name):%0A                return command%0A%0A        raise KeyError('Could not identify prefix of opt %7B%7D'.format(opt_name))%0A%0A
     def proc
@@ -3639,32 +3639,32 @@
 _options(self):%0A
-
         for opti
@@ -3993,68 +3993,8 @@
 ''%0A%0A
-            from_install = (%0A                'install_'%0A    
     
@@ -4011,20 +4011,16 @@
  option 
-not 
 in cmdop
@@ -4049,21 +4049,17 @@
 ptions'%5D
- else
+:
 %0A       
@@ -4066,16 +4066,25 @@
         
+ prefix =
  ''%0A    
@@ -4091,17 +4091,97 @@
         
-)
+else:%0A                prefix = '%7B%7D_'.format(self.determine_opt_prefix(opt_name))%0A
 %0A       
@@ -4388,20 +4388,14 @@
 fix=
-from_install
+prefix
 ,%0A  

Improve prefix calculation of reqfile option autogeneration