1from __future__ import absolute_import 2 3import sys 4import textwrap 5 6from pip._internal.cli.base_command import Command 7from pip._internal.cli.status_codes import SUCCESS 8from pip._internal.utils.misc import get_prog 9from pip._internal.utils.typing import MYPY_CHECK_RUNNING 10 11if MYPY_CHECK_RUNNING: 12 from optparse import Values 13 from typing import List 14 15BASE_COMPLETION = """ 16# pip {shell} completion start{script}# pip {shell} completion end 17""" 18 19COMPLETION_SCRIPTS = { 20 'bash': """ 21 _pip_completion() 22 {{ 23 COMPREPLY=( $( COMP_WORDS="${{COMP_WORDS[*]}}" \\ 24 COMP_CWORD=$COMP_CWORD \\ 25 PIP_AUTO_COMPLETE=1 $1 2>/dev/null ) ) 26 }} 27 complete -o default -F _pip_completion {prog} 28 """, 29 'zsh': """ 30 function _pip_completion {{ 31 local words cword 32 read -Ac words 33 read -cn cword 34 reply=( $( COMP_WORDS="$words[*]" \\ 35 COMP_CWORD=$(( cword-1 )) \\ 36 PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null )) 37 }} 38 compctl -K _pip_completion {prog} 39 """, 40 'fish': """ 41 function __fish_complete_pip 42 set -lx COMP_WORDS (commandline -o) "" 43 set -lx COMP_CWORD ( \\ 44 math (contains -i -- (commandline -t) $COMP_WORDS)-1 \\ 45 ) 46 set -lx PIP_AUTO_COMPLETE 1 47 string split \\ -- (eval $COMP_WORDS[1]) 48 end 49 complete -fa "(__fish_complete_pip)" -c {prog} 50 """, 51} 52 53 54class CompletionCommand(Command): 55 """A helper command to be used for command completion.""" 56 57 ignore_require_venv = True 58 59 def add_options(self): 60 # type: () -> None 61 self.cmd_opts.add_option( 62 '--bash', '-b', 63 action='store_const', 64 const='bash', 65 dest='shell', 66 help='Emit completion code for bash') 67 self.cmd_opts.add_option( 68 '--zsh', '-z', 69 action='store_const', 70 const='zsh', 71 dest='shell', 72 help='Emit completion code for zsh') 73 self.cmd_opts.add_option( 74 '--fish', '-f', 75 action='store_const', 76 const='fish', 77 dest='shell', 78 help='Emit completion code for fish') 79 80 self.parser.insert_option_group(0, self.cmd_opts) 81 82 def run(self, options, args): 83 # type: (Values, List[str]) -> int 84 """Prints the completion code of the given shell""" 85 shells = COMPLETION_SCRIPTS.keys() 86 shell_options = ['--' + shell for shell in sorted(shells)] 87 if options.shell in shells: 88 script = textwrap.dedent( 89 COMPLETION_SCRIPTS.get(options.shell, '').format( 90 prog=get_prog()) 91 ) 92 print(BASE_COMPLETION.format(script=script, shell=options.shell)) 93 return SUCCESS 94 else: 95 sys.stderr.write( 96 'ERROR: You must pass {}\n' .format(' or '.join(shell_options)) 97 ) 98 return SUCCESS 99