Skip to content

Improve support for autocompletion: shell_complete vs autocompletion #949

Closed
@tiangolo

Description

@tiangolo

Privileged issue

  • I'm @tiangolo or he asked me directly to create an issue here.

Issue Content

In Short

We want a single parameter to handle CLI parameter autocompletion, based on type annotations.

Current State

Right now the Typer docs only talk about the function for the parameter autocompletion.

And Typer has (proper) support for that function based on type annotations.

It checks the types for a Context, list[str] for other args, and str for the current incomplete args: https://typer.tiangolo.com/tutorial/options-autocompletion/#types-types-everywhere

The support for autocompletion is based on the type annotations (like the rest of Typer), not on the order or name of the arguments.

Now with Click 8.x the underlying parameter autocompletion was removed and there's a new one shell_complete (https://click.palletsprojects.com/en/8.1.x/api/#click.ParamType.shell_complete).

In Typer, autocompletion raises a warning already: https://github.com/fastapi/typer/blob/master/typer/core.py#L65

But there are no docs nor proper support for shell_complete based on type annotations.

We Want

We want to have support for completion based on type annotations. The parameter should be able to expect a Context and a str with the incomplete parameter. But I'm not sure of the parameter name for this function.

Note: we probably don't need to support list[str] for extra args as that's available from context.args.

We should have that as the main documented feature. We could have a note at the end mentioning that there's a (now deprecated) autocompletion parameter, with the basics of how it worked, but the main functionality would be with the new parameter.

Hardest Problem in CS: Naming

Writing this I'm realizing that in Typer I'm using the same parameter name that was available in Click: autocompletion, but in reality, it has different semantics.

In Click, the meaning of the parameters is based on the position/order.

In Click 7.x it had to be in the exact order of ctx, args, incomplete:

def get_colors(ctx, args, incomplete):
    ...

In Click 8.x it has to be the exact order of ctx, param, incomplete:

def complete_env_vars(ctx, param, incomplete):
    ...

In Typer, autocompletion it's based on the type annotations, which also means that the order doesn't matter, if all of the parameters are present or not doesn't matter, the name of the parameters doesn't matter. The only thing that matters is the type annotations: https://typer.tiangolo.com/tutorial/options-autocompletion/#types-types-everywhere

This means that the name of the parameter autocompletion is the same as in Click, but the semantics are actually not the same. 🤔

That makes me think that maybe the parameter should have a different name, so that people don't get confused with it assuming it's the same as in Click, and it really is not, at least not in the same way.

Maybe we should just keep the same name autocompletion just because that's the main name we've had documented in Typer. 🤔

My original thought was to support a parameter shell_complete (like the one in Click) but based on type annotations. But now thinking about it, I think maybe it makes more sense to have a different name (or just keep the old autocompletion name). And have it based on type annotations.

I think the new/final parameter should be able to request (via type annotations) the Context and the incomplete str. I don't think we should support it requesting the param Click Parameter until we find a reason to do so (I can't find any yet).

The other thing is, the old Click autocompletion supported returning str values or tuples. The new shell_complete expects objects of type CompletionItem, but I wouldn't think requiring users to import that class and create instances of it would be a great developer experience, so I would prefer to keep supporting the older syntax too.

Note on CompletionItem

From the source, I understand that the main thing it provides apart from the previously supported data is a new type that tells the completion parts if the thing to complete is a directory or file... I'm not sure in which cases that type is useful, maybe internally, but not sure for completion functions. And also, if there's a use case where that makes sense, we can probably know the type from the type annotation (e.g. Path).

Metadata

Metadata

Assignees

Labels

featureNew feature, enhancement or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions