typer.completion
1import os 2import sys 3from typing import Any, MutableMapping, Tuple 4 5import click 6 7from ._completion_classes import completion_init 8from ._completion_shared import Shells, get_completion_script, install 9from .models import ParamMeta 10from .params import Option 11from .utils import get_params_from_function 12 13try: 14 import shellingham 15except ImportError: # pragma: no cover 16 shellingham = None 17 18try: 19 import rich 20 21except ImportError: # pragma: no cover 22 rich = None # type: ignore 23 24 25_click_patched = False 26 27 28def get_completion_inspect_parameters() -> Tuple[ParamMeta, ParamMeta]: 29 completion_init() 30 test_disable_detection = os.getenv("_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION") 31 if shellingham and not test_disable_detection: 32 parameters = get_params_from_function(_install_completion_placeholder_function) 33 else: 34 parameters = get_params_from_function( 35 _install_completion_no_auto_placeholder_function 36 ) 37 install_param, show_param = parameters.values() 38 return install_param, show_param 39 40 41def install_callback(ctx: click.Context, param: click.Parameter, value: Any) -> Any: 42 if not value or ctx.resilient_parsing: 43 return value # pragma: no cover 44 if isinstance(value, str): 45 shell, path = install(shell=value) 46 else: 47 shell, path = install() 48 click.secho(f"{shell} completion installed in {path}", fg="green") 49 click.echo("Completion will take effect once you restart the terminal") 50 sys.exit(0) 51 52 53def show_callback(ctx: click.Context, param: click.Parameter, value: Any) -> Any: 54 if not value or ctx.resilient_parsing: 55 return value # pragma: no cover 56 prog_name = ctx.find_root().info_name 57 assert prog_name 58 complete_var = "_{}_COMPLETE".format(prog_name.replace("-", "_").upper()) 59 shell = "" 60 test_disable_detection = os.getenv("_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION") 61 if isinstance(value, str): 62 shell = value 63 elif shellingham and not test_disable_detection: 64 shell, _ = shellingham.detect_shell() 65 script_content = get_completion_script( 66 prog_name=prog_name, complete_var=complete_var, shell=shell 67 ) 68 click.echo(script_content) 69 sys.exit(0) 70 71 72# Create a fake command function to extract the completion parameters 73def _install_completion_placeholder_function( 74 install_completion: bool = Option( 75 None, 76 "--install-completion", 77 callback=install_callback, 78 expose_value=False, 79 help="Install completion for the current shell.", 80 ), 81 show_completion: bool = Option( 82 None, 83 "--show-completion", 84 callback=show_callback, 85 expose_value=False, 86 help="Show completion for the current shell, to copy it or customize the installation.", 87 ), 88) -> Any: 89 pass # pragma: no cover 90 91 92def _install_completion_no_auto_placeholder_function( 93 install_completion: Shells = Option( 94 None, 95 callback=install_callback, 96 expose_value=False, 97 help="Install completion for the specified shell.", 98 ), 99 show_completion: Shells = Option( 100 None, 101 callback=show_callback, 102 expose_value=False, 103 help="Show completion for the specified shell, to copy it or customize the installation.", 104 ), 105) -> Any: 106 pass # pragma: no cover 107 108 109# Re-implement Click's shell_complete to add error message with: 110# Invalid completion instruction 111# To use 7.x instruction style for compatibility 112# And to add extra error messages, for compatibility with Typer in previous versions 113# This is only called in new Command method, only used by Click 8.x+ 114def shell_complete( 115 cli: click.Command, 116 ctx_args: MutableMapping[str, Any], 117 prog_name: str, 118 complete_var: str, 119 instruction: str, 120) -> int: 121 import click 122 import click.shell_completion 123 124 if "_" not in instruction: 125 click.echo("Invalid completion instruction.", err=True) 126 return 1 127 128 # Click 8 changed the order/style of shell instructions from e.g. 129 # source_bash to bash_source 130 # Typer override to preserve the old style for compatibility 131 # Original in Click 8.x commented: 132 # shell, _, instruction = instruction.partition("_") 133 instruction, _, shell = instruction.partition("_") 134 # Typer override end 135 136 comp_cls = click.shell_completion.get_completion_class(shell) 137 138 if comp_cls is None: 139 click.echo(f"Shell {shell} not supported.", err=True) 140 return 1 141 142 comp = comp_cls(cli, ctx_args, prog_name, complete_var) 143 144 if instruction == "source": 145 click.echo(comp.source()) 146 return 0 147 148 # Typer override to print the completion help msg with Rich 149 if instruction == "complete": 150 if not rich: # pragma: no cover 151 click.echo(comp.complete()) 152 else: 153 from . import rich_utils 154 155 rich_utils.print_with_rich(comp.complete()) 156 157 return 0 158 # Typer override end 159 160 click.echo(f'Completion instruction "{instruction}" not supported.', err=True) 161 return 1
29def get_completion_inspect_parameters() -> Tuple[ParamMeta, ParamMeta]: 30 completion_init() 31 test_disable_detection = os.getenv("_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION") 32 if shellingham and not test_disable_detection: 33 parameters = get_params_from_function(_install_completion_placeholder_function) 34 else: 35 parameters = get_params_from_function( 36 _install_completion_no_auto_placeholder_function 37 ) 38 install_param, show_param = parameters.values() 39 return install_param, show_param
def
install_callback(ctx: click.core.Context, param: click.core.Parameter, value: Any) -> Any:
42def install_callback(ctx: click.Context, param: click.Parameter, value: Any) -> Any: 43 if not value or ctx.resilient_parsing: 44 return value # pragma: no cover 45 if isinstance(value, str): 46 shell, path = install(shell=value) 47 else: 48 shell, path = install() 49 click.secho(f"{shell} completion installed in {path}", fg="green") 50 click.echo("Completion will take effect once you restart the terminal") 51 sys.exit(0)
def
show_callback(ctx: click.core.Context, param: click.core.Parameter, value: Any) -> Any:
54def show_callback(ctx: click.Context, param: click.Parameter, value: Any) -> Any: 55 if not value or ctx.resilient_parsing: 56 return value # pragma: no cover 57 prog_name = ctx.find_root().info_name 58 assert prog_name 59 complete_var = "_{}_COMPLETE".format(prog_name.replace("-", "_").upper()) 60 shell = "" 61 test_disable_detection = os.getenv("_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION") 62 if isinstance(value, str): 63 shell = value 64 elif shellingham and not test_disable_detection: 65 shell, _ = shellingham.detect_shell() 66 script_content = get_completion_script( 67 prog_name=prog_name, complete_var=complete_var, shell=shell 68 ) 69 click.echo(script_content) 70 sys.exit(0)
def
shell_complete( cli: click.core.Command, ctx_args: MutableMapping[str, Any], prog_name: str, complete_var: str, instruction: str) -> int:
115def shell_complete( 116 cli: click.Command, 117 ctx_args: MutableMapping[str, Any], 118 prog_name: str, 119 complete_var: str, 120 instruction: str, 121) -> int: 122 import click 123 import click.shell_completion 124 125 if "_" not in instruction: 126 click.echo("Invalid completion instruction.", err=True) 127 return 1 128 129 # Click 8 changed the order/style of shell instructions from e.g. 130 # source_bash to bash_source 131 # Typer override to preserve the old style for compatibility 132 # Original in Click 8.x commented: 133 # shell, _, instruction = instruction.partition("_") 134 instruction, _, shell = instruction.partition("_") 135 # Typer override end 136 137 comp_cls = click.shell_completion.get_completion_class(shell) 138 139 if comp_cls is None: 140 click.echo(f"Shell {shell} not supported.", err=True) 141 return 1 142 143 comp = comp_cls(cli, ctx_args, prog_name, complete_var) 144 145 if instruction == "source": 146 click.echo(comp.source()) 147 return 0 148 149 # Typer override to print the completion help msg with Rich 150 if instruction == "complete": 151 if not rich: # pragma: no cover 152 click.echo(comp.complete()) 153 else: 154 from . import rich_utils 155 156 rich_utils.print_with_rich(comp.complete()) 157 158 return 0 159 # Typer override end 160 161 click.echo(f'Completion instruction "{instruction}" not supported.', err=True) 162 return 1