diff --git a/src/dotnet/NOTES.md b/src/dotnet/NOTES.md index ff52835b0..2928a6779 100644 --- a/src/dotnet/NOTES.md +++ b/src/dotnet/NOTES.md @@ -90,3 +90,21 @@ Installing prerelease builds. Supports `preview` and `daily` suffixes. This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed. `bash` is required to execute the `install.sh` script. + +## Tab completions + +When using .NET SDK 10 or newer, tab completions for the `dotnet` CLI are automatically installed for bash, zsh, and fish. The completion scripts are placed in the standard system-wide directories so they work for all users: + +- **Bash**: `/usr/share/bash-completion/completions/dotnet` +- **Zsh**: `/usr/share/zsh/site-functions/_dotnet` +- **Fish**: `/usr/share/fish/vendor_completions.d/dotnet.fish` + +To disable this, set `tabCompletions` to `false`: + +``` json +"features": { + "ghcr.io/devcontainers/features/dotnet:2": { + "tabCompletions": false + } +} +``` diff --git a/src/dotnet/devcontainer-feature.json b/src/dotnet/devcontainer-feature.json index 7389b8398..4bd3168c7 100644 --- a/src/dotnet/devcontainer-feature.json +++ b/src/dotnet/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "dotnet", - "version": "2.4.2", + "version": "2.5.0", "name": "Dotnet CLI", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/dotnet", "description": "This Feature installs the latest .NET SDK, which includes the .NET CLI and the shared runtime. Options are provided to choose a different version or additional versions.", @@ -39,6 +39,11 @@ "type": "string", "default": "", "description": "Enter additional .NET SDK workloads, separated by commas. Use 'dotnet workload search' to learn what workloads are available to install." + }, + "tabCompletions": { + "type": "boolean", + "default": true, + "description": "Install shell tab completions for the dotnet CLI. Requires SDK 10 or newer." } }, "containerEnv": { @@ -64,4 +69,4 @@ "installsAfter": [ "ghcr.io/devcontainers/features/common-utils" ] -} +} \ No newline at end of file diff --git a/src/dotnet/install.sh b/src/dotnet/install.sh index a6bde1ebd..afd6bd287 100644 --- a/src/dotnet/install.sh +++ b/src/dotnet/install.sh @@ -11,6 +11,7 @@ ADDITIONAL_VERSIONS="${ADDITIONALVERSIONS:-""}" DOTNET_RUNTIME_VERSIONS="${DOTNETRUNTIMEVERSIONS:-""}" ASPNETCORE_RUNTIME_VERSIONS="${ASPNETCORERUNTIMEVERSIONS:-""}" WORKLOADS="${WORKLOADS:-""}" +TAB_COMPLETIONS="${TABCOMPLETIONS:-"true"}" # Prevent "Welcome to .NET" message from dotnet export DOTNET_NOLOGO=true @@ -146,6 +147,10 @@ if [ ! -e /usr/bin/dotnet ]; then ln --symbolic "$DOTNET_ROOT/dotnet" /usr/bin/dotnet fi +if [ "$TAB_COMPLETIONS" = "true" ]; then + install_completions +fi + # Add .NET Core SDK tools to PATH for bash and zsh users # This is where 'dotnet tool install --global ' installs tools to # Use single-quoted EOF to defer $PATH expansion until sourcing the file diff --git a/src/dotnet/scripts/dotnet-helpers.sh b/src/dotnet/scripts/dotnet-helpers.sh index 2ef8796eb..a7eee84d3 100644 --- a/src/dotnet/scripts/dotnet-helpers.sh +++ b/src/dotnet/scripts/dotnet-helpers.sh @@ -184,4 +184,46 @@ parse_version_and_quality() { quality="" fi echo "$clean_version" "$quality" +} + +# Checks if the installed .NET SDK is at least the given major version. +# Returns 0 (true) if the SDK major version >= the specified version, 1 otherwise. +# Also returns 1 if no SDK is installed (e.g. runtime-only installs). +# Usage: is_at_least_sdk_version +# Example: is_at_least_sdk_version 10 +is_at_least_sdk_version() { + local required_major="$1" + local dotnet_version + dotnet_version=$("$DOTNET_ROOT/dotnet" --version 2>/dev/null || true) + local major_version="${dotnet_version%%.*}" + [[ "$major_version" =~ ^[0-9]+$ ]] && [ "$major_version" -ge "$required_major" ] +} + +# Sets up dotnet tab completions for bash, zsh, and fish. +# The 'dotnet completions script' command is only available in .NET SDK 10+. +# Older SDKs and runtime-only installs will naturally skip this since the +# command won't be available. +# Reference: https://learn.microsoft.com/en-us/dotnet/core/tools/enable-tab-autocomplete +# Completion scripts are generated at install time and placed in the standard +# system-wide completion directories, which are auto-discovered by +# bash-completion, zsh, and fish without modifying any rc files. +install_completions() { + if ! is_at_least_sdk_version 10; then + echo "Skipping dotnet tab completions (requires SDK 10+)." + return + fi + + echo "Setting up dotnet tab completions..." + + # Bash: drop into the standard bash-completion directory + mkdir -p /usr/share/bash-completion/completions + "$DOTNET_ROOT/dotnet" completions script bash > /usr/share/bash-completion/completions/dotnet + + # Zsh: drop into the standard site-functions directory + mkdir -p /usr/share/zsh/site-functions + "$DOTNET_ROOT/dotnet" completions script zsh > /usr/share/zsh/site-functions/_dotnet + + # Fish: drop into the standard vendor completions directory + mkdir -p /usr/share/fish/vendor_completions.d + "$DOTNET_ROOT/dotnet" completions script fish > /usr/share/fish/vendor_completions.d/dotnet.fish } \ No newline at end of file diff --git a/test/dotnet/test.sh b/test/dotnet/test.sh index 11cc73126..7c5591773 100644 --- a/test/dotnet/test.sh +++ b/test/dotnet/test.sh @@ -21,9 +21,18 @@ test -L /usr/bin/dotnet -a "$(readlink -f /usr/bin/dotnet)" = "$DOTNET_ROOT/dotn expected=$(fetch_latest_version) -check "Latest .NET SDK version installed" \ +check "Latest .NET SDK version $expected installed" \ is_dotnet_sdk_version_installed "$expected" +check "Bash completion script installed" \ +test -s /usr/share/bash-completion/completions/dotnet + +check "Zsh completion script installed" \ +test -s /usr/share/zsh/site-functions/_dotnet + +check "Fish completion script installed" \ +test -s /usr/share/fish/vendor_completions.d/dotnet.fish + # Report results # If any of the checks above exited with a non-zero exit code, the test will fail. reportResults \ No newline at end of file