Bash completion: Honor repository-specific Git alias in alias completion
Asked Answered
Y

1

30

Say bash is configured with the following alias:

alias up="git --git-dir /path/to/backup/.git"

And that particular repository - and only that repository - has the following git alias:

[alias]
backup = commit --allow-empty-message

How can up auto-complete backup?


This auto-completes backup but not up:

cd /a/different/dir
git --git-dir=/path/to/backup/.git ba

This auto-completes up with standard git commands but not backup:

complete -o bashdefault -o default -o nospace -F __git_wrap__git_main up


Edit: Etan is right, the completion function needs to see the expanded alias, so I've created the following:

CompletableAlias() {
    if (($#<2)); then
        return 1
    fi
    source_c="$1"
    target_c="$2"
    target_a=( "${@:2}" )
    target_s="${target_a[*]}"
    alias "${source_c}=${target_s}"
    completion_modifier="__${source_c}_completion"
    completion_original="$( complete -p "$target_c" 2>/dev/null |
                            sed 's/.*-F\W\+\(\w\+\).*/\1/'
                          )"
    if [[ -n "$completion_original" ]]; then
        read -r -d '' completion_function <<-EOF
        function $completion_modifier() {
            COMP_LINE="\${COMP_LINE/#${source_c}/${target_s}}"
            ((COMP_POINT+=${#target_s}-${#source_c}))
            ((COMP_CWORD+=${#target_a[@]}-1))
            COMP_WORDS=( ${target_a[@]} \${COMP_WORDS[@]:1} )
            $completion_original
        }
EOF
        eval "$completion_function"
        completion_command="$( complete -p "$target_c" |
                               sed "s/${completion_original}/${completion_modifier}/;
                                    s/\w\+\$/${source_c}/"
                             )"
        $completion_command
    fi
}


source "/usr/share/bash-completion/completions/git"

CompletableAlias "up" "git" "--git-dir" "/path/to/backup/.git"

But there inexplicable problems:

  • up bac<Tab> doesn't work
  • up <Tab> uses default completion and doesn't list git subcommands
  • and many more ...

Edit 2: Updated the script to fix the aforementioned problems using the suggestions at Re: Bash completion of aliased commands. Apparently this is a pretty common task. However now I'm running into this error message:

$ cd /a/different/dir
$ up backup<Tab> fatal: Not a git repository (or any of the parent directories): .git
Ynez answered 29/4, 2015 at 21:23 Comment(2)
Does the completion function see up or the expanded alias?Frottage
if the completion function reads in the command as 'up' it wont behave as expected, use a secondary function to expand to 'backup' so you can be sure that the exact command is being sent to the completion function. This is how it is with many completer functions, they expect (or assume) that the command is what they programmed it for. Therefore, if you go and attach a completer to some other command, it wont work (hence the middle-man function). To start you might show some output from -xv from calling the two, to make sure your function is doing what you expect (or the diff of it)Wriggle
P
1

You shouldn't really use aliases at such complicated cases, use bash functions. Aliases are more like pre-processor in C (in sense of using), when functions are more like... code functions. And I've found that they are also more "auto-completable".

You can also take a look at how this problem is being solved at other shells, like fish.

Pralltriller answered 7/12, 2015 at 16:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.