Private/Get-AccountCompleter.ps1

function Get-AccountCompleter {
    <#
    .SYNOPSIS
        Provides argument completion for the Account parameter.
 
    .DESCRIPTION
        Returns a scriptblock that can be used with [ArgumentCompleter()]
        to provide tab completion for account names.
 
    .OUTPUTS
        ScriptBlock - Argument completer scriptblock.
 
    .NOTES
        This is a private helper function that returns the completer scriptblock.
    #>

    [CmdletBinding()]
    param()

    return {
        param(
            $commandName,
            $parameterName,
            $wordToComplete,
            $commandAst,
            $fakeBoundParameters
        )

        # Try to get DataPath from bound parameters, otherwise use default
        $dataPath = $fakeBoundParameters['DataPath']
        $budget = $fakeBoundParameters['Budget']

        try {
            # Resolve the data path
            if ($dataPath) {
                $resolvedPath = $dataPath
            }
            elseif ($budget) {
                $resolvedPath = Get-BudgetPath -BudgetName $budget
            }
            else {
                # Try to get active budget
                $preferences = Get-Preferences
                if ($preferences -and $preferences.activeBudget) {
                    $resolvedPath = Get-BudgetPath -BudgetName $preferences.activeBudget
                }
                else {
                    return @()
                }
            }

            # Read accounts
            $accounts = Read-EntityData -EntityType 'Account' -DataPath $resolvedPath

            # Filter and return matching account names
            $accounts | 
                Where-Object { $_.Name -like "$wordToComplete*" } |
                ForEach-Object {
                    $name = $_.Name
                    # Quote names with spaces
                    if ($name -match '\s') {
                        $name = "'$name'"
                    }
                    [System.Management.Automation.CompletionResult]::new(
                        $name,
                        $_.Name,
                        'ParameterValue',
                        "Account: $($_.Name) ($($_.Bank))"
                    )
                }
        }
        catch {
            # Silently fail for completion - don't interrupt user
            return @()
        }
    }
}

# Register the argument completer for all commands that use -Account parameter
$accountCompleterScript = {
    param(
        $commandName,
        $parameterName,
        $wordToComplete,
        $commandAst,
        $fakeBoundParameters
    )

    # Try to get DataPath from bound parameters, otherwise use default
    $dataPath = $fakeBoundParameters['DataPath']
    $budget = $fakeBoundParameters['Budget']

    try {
        # Resolve the data path
        if ($dataPath) {
            $resolvedPath = $dataPath
        }
        elseif ($budget) {
            $resolvedPath = Get-BudgetPath -BudgetName $budget
        }
        else {
            # Try to get active budget
            $preferences = Get-Preferences
            if ($preferences -and $preferences.activeBudget) {
                $resolvedPath = Get-BudgetPath -BudgetName $preferences.activeBudget
            }
            else {
                return @()
            }
        }

        # Read accounts
        $accounts = Read-EntityData -EntityType 'Account' -DataPath $resolvedPath

        # Filter and return matching account names
        $accounts | 
            Where-Object { $_.Name -like "$wordToComplete*" } |
            ForEach-Object {
                $name = $_.Name
                # Quote names with spaces
                if ($name -match '\s') {
                    $name = "'$name'"
                }
                [System.Management.Automation.CompletionResult]::new(
                    $name,
                    $_.Name,
                    'ParameterValue',
                    "Account: $($_.Name) ($($_.Bank))"
                )
            }
    }
    catch {
        # Silently fail for completion - don't interrupt user
        return @()
    }
}

# These will be registered when the module loads
$script:AccountCompleterCommands = @('New-Biller', 'Set-Biller', 'New-Earning', 'Set-Earning')
$script:AccountCompleterScript = $accountCompleterScript