Skip to content

Add shell tab-completion support for flubu commands outside interactive mode #370

Description

@mzorec

Summary

Add shell tab-completion for flubu commands in bash, zsh, PowerShell, and fish. Currently completion only works inside flubu -i interactive mode. Users running normal flubu <target> commands get no tab-completion and must rely on --help or memory.

Motivation

Modern CLIs (dotnet, gh, kubectl, docker) all support shell tab-completion. Users expect to type flubu cl<tab> and get clean completed. This is especially valuable for FlubuCore since target names are user-defined and vary per project — there's no way to know them without looking at the build script or running --help.

Proposed Implementation

1. Add a hidden --completions command

A new option in FlubuCommandParser that outputs matching completions to stdout, one per line:

flubu --completions "flubu cl"
# output:
# clean
# clean.output

flubu --completions "flubu --"
# output:
# --parallel
# --dryrun
# --noColor
# --nodeps
# --script
# --debug

This command needs to:

  • Load the build script (if present) to discover targets from TargetTree
  • Include all registered options from FlubuCommandParser
  • Include script property hints from IScriptProperties.GetPropertiesHints()
  • Match the partial input against available completions (prefix match is sufficient)
  • Output matches to stdout, one per line
  • Exit with code 0

2. Add --setup-completions <shell> command

Outputs the shell-specific completion script that users source once:

# Bash — add to ~/.bashrc
eval "$(flubu --setup-completions bash)"

# Zsh — add to ~/.zshrc
eval "$(flubu --setup-completions zsh)"

# PowerShell — add to $PROFILE
flubu --setup-completions pwsh | Invoke-Expression

# Fish
flubu --setup-completions fish | source

3. Shell completion scripts

Each script registers a completion function that calls flubu --completions "<current-line>" on each tab press.

Bash example:

_flubu_completions() {
    local IFS=$'\n'
    COMPREPLY=($(flubu --completions "${COMP_LINE}" 2>/dev/null))
}
complete -F _flubu_completions flubu

PowerShell example:

Register-ArgumentCompleter -CommandName flubu -Native -ScriptBlock {
    param($wordToComplete, $commandAst, $cursorPosition)
    $completions = flubu --completions "$commandAst" 2>$null
    $completions -split "`n" | ForEach-Object {
        [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
    }
}

What should complete

Input Completes with
flubu <tab> All target names from build script
flubu cl<tab> Targets starting with "cl" (e.g., clean)
flubu --<tab> Global options: --parallel, --dryrun, --noColor, --nodeps, --script, --debug
flubu -s <tab> .cs files in current directory
flubu test --<tab> Target-specific task options (from [ArgKey] attributes)

Existing code to reuse

All the hint/completion data already exists and is used by flubu -i interactive mode:

  • Target discovery: CommandExecutorInteractive.InitializeFlubuConsole() already walks TargetTree
  • Script property hints: IScriptProperties.GetPropertiesHints()
  • Task option hints: FlubuConsole extracts these via [ArgKey] reflection
  • Command hints: GitCommands, DotnetCommands, DockerCommands, ChocolateyCommands

The --completions command just needs to reuse this data and write matches to stdout instead of rendering them in the console.

Why not migrate to System.CommandLine?

Evaluated and rejected because:

  • FlubuCore targets are dynamic (discovered from user build scripts at runtime) — System.CommandLine's model expects static command trees
  • Would require rewriting FlubuCommandParser and all option definitions
  • System.CommandLine requires users to install dotnet-suggest global tool + shell shims — heavier setup
  • Custom --completions is quite easy to implement and gives full control

Why not use McMaster's completion support?

McMaster.Extensions.CommandLineUtils has no shell completion support. Feature requests (#9, #438) were closed. The library is in maintenance mode.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions