Skip to content

Automatically register and improve CLI completions for the dotnet CLI #42397

@baronfel

Description

@baronfel

Is your feature request related to a problem? Please describe.

The dotnet CLI today has pervasive completion support for commands, options, and arguments. However, our telemetry data suggests that very few users do the configuration required to enable completion support in their shells. In the recent CLI usability study, the top-requested item across all users regardless of experience levels, IDE, or OS was automatic registration of CLI completions and more pervasive and informative completions across the CLI commands (and commands that feel like they are part of the dotnet CLI).

Describe the solution you'd like

The dotnet CLI should

  • reduce the work required to register tab completions for shells,
  • invest in statically-generated completion scripts, and
  • expand the information provided from completions to include help descriptions and other reference information

This will bring the CLI in-line with patterns used by other widely-used CLI tools, vastly improve the user experience of the CLI, and improve the performance of completions all-up.

Reduce the work required to register tab completions for shells

Today, users configure completion for their shells by manually inserting shell-specific completion scripts into their shell-specific profile scripts - scripts that shells either explicitly or implicitly by convention load when starting or requesting completions for a command. These scripts are 'frozen' in time and users have to remember to update them if CLI capabilities change.

Instead, we should provide a two new commands to make this process easier:

  • dotnet completions script [<SHELL>]
    • emits the completions script for a particular SHELL to stdout, with no other output allowed from the CLI
    • if no SHELL is specified, infers the shell from the users $SHELL environment variable
  • dotnet completions register [<SHELL>]
    • inserts a shell-specific call to dotnet completions script <SHELL> into a shell-specific completions script location
    • if no SHELL is specified, infers the shell from the users $SHELL environment variable
    • There's a lot of prior art for installation/uninstallation in the golang complete package (MIT licensed).

We should also extend the first-run experience to prompt the user for permission to perform the register command on first-run, but only if the current shell is interactive (meaning a user is at the keyboard). There is an existing go/bash convention for this: COMP_INSTALL=1 and COMP_UNINSTALL=1 environment variables signal willingness to automatically configure and remove completions for programs.

Invest in statically-generated completion scripts

With the previous step done, we now have a way to solve the 'out of date completions script' problem. User shells will automatically generate and load completions scripts on each load, so the dotnet CLI can begin investments in generating better scripts.

The first iteration of the dotnet completions script [<SHELL>] command would only emit the 'dynamic' completion script that we ask users to set up today. However, subsequent iterations should generate scripts that are more static - meaning they generation completions without having to call dotnet complete, instead relying on the features of the different shell completion systems to prevent the need to spawn dotnet processes (with all the overhead that entails) and enable better shell-completion-system integration and performance overall.

This can be done opportunistically and at different levels for different shells, because many shells have varying degrees of sophistication here.

Expand the information provided from completions

Today, all completions for the dotnet CLI provide only the completion value. The underlying System.CommandLine completions subsystem allows for providing more details, like descriptions or extended help for a given completion item. The completions systems for different shells are often capable of rendering this information inline when completions are requested, but it has been hard to provide that information in a way that didn't invalidate the existing shell script shims that users have added to their profiles.

With dotnet completions register [<$SHELL>] all of these blockers are removed and we can create new completion commands to provide whatever level of context is required. At minimum we should provide descriptions and integrate them into the statically-generated completions from the previous section.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-CLIEpicGroups multiple user stories. Can be grouped under a theme.cli-uxIssues and PRs that deal with the UX of the CLI (exit codes, log output, verbs/options, and so on)untriagedRequest triage from a team member

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions